问题
我打算为Linux编写一个C++ 11应用程序,该应用程序基于大约一百万个伪随机32位数字进行一些数值模拟(而不是加密)。为了加快速度,我想使用台式机CPU的所有内核在并行线程中执行仿真。我想将boost提供的Mersenne Twister mt19937
用作PRNG,并且我想出于性能原因,每个线程应该有一个这样的PRNG。现在,我不确定如何播种它们,以避免在多个线程中生成相同的随机数子序列。
备择方案
到目前为止,我已经想到了以下替代方案:
/dev/urandom
为每个线程播种PRNG。我有点担心系统熵池耗尽的情况,因为我不知道系统内部PRNG的工作方式。由于
/dev/urandom
使用的是Mersenne Twister本身,我是否偶然得到了连续的种子,它们准确地标识了Mersenne Twister的连续状态?可能与我对下一点的担忧密切相关。/dev/urandom
播种一个PRNG,并从第一个PRNG播种。基本上也有相同的问题:使用一个PRNG播种使用相同算法的另一个PRNG是好是坏?或者换句话说,从
mt19937
读取625个32位整数是否直接对应于mt19937
生成器在生成过程中的任何时刻的内部状态?由于使用相同的算法来生成随机数并生成初始种子似乎有点不好,所以我考虑引入一些不依赖于Mersenne Twister算法的元素。例如,我可以将线程ID异或到初始种子 vector 的每个元素中。这会使事情变得更好吗?
这样可以确保只有一个序列具有Mersenne Twister的所有已知和理想特性。但是控制访问该生成器所需的锁定开销确实让我有些担心。由于我没有发现相反的证据,因此我假设我作为库用户将负责阻止并发访问PRNG。
这将使一个线程预先生成所有必需的1M随机数,以供以后的不同线程使用。与整个应用程序相比,4M的内存需求将很小。这种方法让我最担心的是,随机数的生成本身并不是并发的。整个方法的伸缩性也不太好。
问题
您会建议采用哪种方法?为什么?还是您有其他建议?
您知道我的哪些担忧是正当的,哪些仅是由于我对事情的实际运行缺乏洞察力所致?
最佳答案
我会用一个实例来播种其他实例。我敢肯定,您可以轻松安全地完成此操作。