问题
我打算在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
生成器在任何时刻的内部状态?使用来自第一个 PRNG 的非Mersenne信息为其他 PRNG 提供种子。
采用同一算法生成随机数和初始种子可能不是一个好主意,因此我考虑引入一些不依赖于Mersenne Twister算法的元素。例如,可以将线程ID与每个初始种子向量元素进行异或运算。这样做是否会改善情况?
在线程之间共享一个PRNG。
这将确保只有一个序列,具有所有已知和理想的Mersenne Twister属性。但是,控制对该生成器的访问所需的锁定开销使我有些担忧。由于我没有找到相反的证据,我假设作为库用户,我将负责防止并发访问PRNG。
预先生成所有随机数。
这将使一个线程预先生成所有所需的1M随机数,以供稍后在不同的线程中使用。与整个应用程序相比,4M的内存需求很小。我最担心的是随机数的生成本身不是并发的。这种方法也无法很好地扩展。
问题
你推荐哪种方法,为什么?或者你有其他建议吗?
你知道我的哪些担忧是合理的,哪些只是由于我对事情实际运作的了解不足而产生的吗?
SecureRandom
生成的UUID中获取种子,而不仅仅是Mersenne Twister。 - MvG