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

What is a good way to seed parallel pseudo random number generators?

本文关键字:方法 是什么 并行 随机数生成器 种子      更新时间:2023-10-16

我写的PRNG的周期是2^64。当我使用自旋锁来保护它不受4个线程的影响时,它的运行速度比单线程时慢两倍。互斥锁似乎更能让事情变慢。所以我决定每个线程有单独的生成器,但这里的问题是,当种子太接近时,相同的随机数系列将一次又一次地出现在不同的线程中。我不能100%确定这对我的模拟有多糟糕,但我希望避免使用非常紧密的种子prng。

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

我发现,随着并行生成器的数量或生成的随机数的数量或两者都增加,找到"最佳"种子集变得越来越困难。每个任务将至少有4个线程和至少10亿个随机数。

I我能达到的最简单的解决方案是周期性播种。有时我可能会得到一组不好的种子,但经过周期性的重新播种,它很快就会被更好的种子所取代。

我的问题是否有一个通用的解决方案,可以应用于任何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;
}

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

好吧,如果你愿意改变RNG,有一些生成器可以快速(跳过调用数的对数倍)跳过(又名跳蛙)。

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

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

更复杂的一个(我相信它通过了虎胆龙威)在这里http://www.pcg-random.org/

均基于快速幂,F. Brown的论文,"任意跨距的随机数生成",译。点。诊断。Soc。(1994年11月)

如果您可以访问加密库,那么您可以使用AES加密填充的初始种子,并在prng之间分割输出。例如,使用带有64位初始种子[seed]的计数器模式,您将将其连接直到得到256位的明文:

(种子)(种子)(种子)(种子)

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

根据加密库中提供的内容,还有其他方法可以做到这一点,例如,您可以散列初始种子,或者您可以生成随机uuid,直到您有足够的位来播种所有prng。