mersenne twister 线程对 cpp 是不是安全
Posted
技术标签:
【中文标题】mersenne twister 线程对 cpp 是不是安全【英文标题】:Is mersenne twister thread safe for cppmersenne twister 线程对 cpp 是否安全 【发布时间】:2017-04-01 01:10:59 【问题描述】:#include <random>
int f()
std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
多个线程可以安全地调用这个函数吗?函数线程安全吗?
每次都打电话std::random_device seeder;
和std::mt19937 engine(seeder());
是多余的吗?
【问题讨论】:
为什么是“C”标签?这与 C 无关。 我真的不明白为什么我会收到反对票。我在问这是否是线程安全的,以及更新种子是否是多余的。 可能是因为类似问题的答案冗长而详细? 您的代码不足以说明线程安全的含义。初始化?一代?多个实例? How do I generate thread-safe uniform random numbers?的可能重复 【参考方案1】:No C++ std
类型以非线程安全的方式使用全局数据。这种类型的两个不相关的实例可以在不同的线程中访问。
默认情况下,一个类型的一个实例不能在没有同步的情况下被两个线程访问。
您被创建了局部变量。这些局部变量与其类型的任何其他实例无关。这里没有线程安全问题。
通过拥有状态并重用它来最有效地生成伪随机值。您没有这样做,因此创建 1 到 6 的随机数会相对昂贵。
std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
您对std::mt19937
的使用是多余的。您已经创建了一个random_device
,可以直接将其提供给dist
,然后从中创建一个engine
,然后使用engine
。在这里使用engine
是没用的。
传统上,您从seeder
创建一个engine
(某种类型,例如mt19937
)一次。然后存储engine
,并反复将其传递给发行版。
这会执行一次相对昂贵的“真实随机数”生成,以通过引擎通过分发生成一长串伪随机数。
但是请注意,这种使用是有代价的;您必须存储 engine
并且必须防止多线程访问它。
执行此操作的“正确”方法是拥有一个为您生成随机值的对象,并将其传递到您需要的地方。存储使用的初始种子还允许您重复执行所涉及的一组随机数。
如果您不喜欢明确传递随机状态的想法,您可以使用thread_local
(或static
和mutex
保护)。
thread_local std::mt19937 engine(std::random_device());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
这会为每个线程创建一个engine
,并且engine
会使用您的random_device
中的值进行初始化。
【讨论】:
【参考方案2】:多个线程可以安全地调用这个函数吗?函数线程安全吗?
这个特殊的函数是线程安全的。可以创建随机数生成器、引擎和分布,在函数本地引擎中多线程调用生成数。
当然,来自多个线程的输出可以交错,因为cout
不同步。
是否需要在每个函数调用中初始化引擎
这就是你的函数所做的,虽然这确实保证了线程安全,但它与你需要做的相反。每次初始化引擎都会使“随机”序列直接依赖于播种机。而且它当然会增加初始化引擎的开销。
或者将前两行(种子和引擎)放在类构造函数中会更好吗?
您可以使用包装类,但不是必须的。这与您是否在每个函数调用中创建一个新的引擎实例是正交的。只要每个函数调用使用与之前调用相同的引擎,这方面的随机性就没有问题。
但是跨线程使用相同的引擎确实不是线程安全的。您可以改为在每个线程中使用一个引擎 - 或使用互斥锁保护共享引擎,但这会产生大量开销。
【讨论】:
以上是关于mersenne twister 线程对 cpp 是不是安全的主要内容,如果未能解决你的问题,请参考以下文章
Mersenne Twister 与 Mersenne Twister 64 位
C# Mersenne Twister 随机整数生成器实现 (SFMT) 蒙特卡罗模拟
伪随机数生成算法-梅森旋转(Mersenne Twister/MT)