种子并行伪随机数生成器的好方法是什么?

时间:2015-08-29 00:38:29

标签: c++ c multithreading random language-agnostic

我写的PRNG的周期是2 ^ 64。当我使用自旋锁来保护它免受4个线程的攻击时,它比单个线程运行速度慢两倍。互斥体似乎更容易使事情变慢。所以我决定每个线程都有单独的生成器,但问题是当种子太近时,同一系列的随机数将一次又一次地出现在不同的线程中。我不是百分之百确定这会对我的模拟造成多大的影响,但我想避免使用种子密切的PRNG。

也许我的原始问题太少,无法获得简单的解决方案。下面我发布了我正在使用的PRNG。它在Diehard或FIPS等统计测试中表现非常出色,但我真的无法证明为什么我不是这方面的专家。我需要一种方法来为4个或更多并行运行的发电机找到好的种子。使用2个种子,最差的种子对是相同的种子,因此2个线程获得相同的随机数序列。最好的一对种子将产生两个没有重叠部分的序列。

我发现随着并行发电机的数量或产生的随机数的数量或两者都变得更大,找到“最佳”种子集会变得更加困难。每个任务至少会生成4个线程和至少10亿个随机数。

我能达到的最简单的解决方案是定期重播。有时我可能得到一组糟糕的种子,但在定期重新种植后很快就会被更好的种子取代。

我的问题有一般解决方案可以应用于任何PRNG吗?或至少我正在使用的发电机可用的东西?我可以改变我的PRNG,如果有一个专门设计并且非常适合并行随机数生成。

static thread_local unsigned long long n;

void seedRand(unsigned long long s)
{
  n = s;
}

unsigned genRand(void)
{
  n *= 123456789;
  n ^= n >> 3;
  n ^= n << 5;
  return n ^= n >> 7;
}

2 个答案:

答案 0 :(得分:1)

如果您有权访问加密库,则可以使用AES加密填充的初始种子,并在PRNG之间拆分输出。例如,使用带有[seed]的64位初始种子的counter mode,你可以连接这个,直到你得到256位的明文:

[种子] [种子] [种子] [种子]

并且您的初始化向量将是[counter] [seed](您需要一个唯一的初始化向量,但不一定是安全的初始化向量,因为没有人试图解密您的输出)。这将产生256位输出,第一个64位接种第一个PRNG,第二个64位接种第二个PRNG等等。

还有其他方法可以执行此操作,具体取决于加密库中提供的内容,例如:你可以hash初始种子,或者你可以产生random UUIDs,直到你有足够的比特来为你的所有PRNG播种。

答案 1 :(得分:1)

  

我可以改变我的PRNG,如果有专门设计并且非常适合并行随机数生成的那个

好吧,如果你愿意改变RNG,那么有些发电机快速(跳过调用次数的对数)跳过(a.k.a leap-frog)。

他们的设计保证不重叠。比方说,你的每个线程的模拟需要10 ^ 9个RNG调用并且可以在8个线程上运行,然后你从单个种子开始,第一个线程被跳过0,第二个线程被跳过10 ^ 9,并且线程数N被跳过(N-1)* 10 ^ 9。

合理可接受的一个(这是MCNP5 fortran代码的重新实现)在这里https://github.com/Iwan-Zotow/LCG-PLE63,但很可能没有通过Diehard。

有点复杂的(我相信它通过了Diehard)http://www.pcg-random.org/

两者都基于快速取幂,F.Brown撰写的论文,&#34;随机数字随机数生成,&#34;跨。上午。核酸研究SOC。 (1994年11月)