c - 播种许多 PRNG,然后不得不再次播种,什么是高质量的方法?

标签 c random

我有许多并行遵循随机过程的粒子。对于每个粒子,都有一个与之关联的 PRNG。 模拟必须经过多次重复才能得到平均结果。对于每次重复,应在模拟开始前为每个粒子选择一个独有的 PRNG 种子。

我第一次得到 seed = time(NULL) 作为 particle1 的种子。对于其余部分,我只是执行 particle2 = seed + 1particle3 = seed + 2 等,所以所有粒子最终都有不同的种子。

在每次重复时,计划是为从 time(NULL) 获得的初始种子添加一个偏移量,例如 seed = seed + all_particles_offset; 然后使用前面描述的方法为每个粒子分配不同的种子。 我的问题是这种方法是否会导致可接受的随机性质量?我不关心安全性,只关心并行运行的随机数的质量以及进程不时重新播种的事实。

顺便说一句,使用的PRNG是PCG。

最佳答案

时间不是一个好种子,因为它太容易预测了。如果您经常需要种子,它也有被重复使用的风险。为避免这种情况,通常用进程和/或线程 ID 等其他内容来置换时间。

更好的是从操作系统的随机源中获取种子,例如 /dev/random或非阻塞版本 /dev/urandom。这将使用环境噪音和其他来源为您提供良好的随机种子。

你可以把它们结合起来,这就是Ruby's Random#new_seed

    /* This gets a seed from /dev/urandom */
    fill_random_bytes(seed, sizeof(*seed));

    /* This further permutes the seed with the time and pid */
    gettimeofday(&tv, 0);
    seed[0] ^= tv.tv_usec;
    seed[1] ^= (uint32_t)tv.tv_sec;
#if SIZEOF_TIME_T > SIZEOF_INT
    seed[0] ^= (uint32_t)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
#endif
    seed[2] ^= getpid() ^ (n++ << 16);
    seed[3] ^= (uint32_t)(VALUE)&seed;
#if SIZEOF_VOIDP > SIZEOF_INT
    seed[2] ^= (uint32_t)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
#endif

您可以从 random.c 中提取他们的随机种子代码.


为了避免从 /dev/random 中进行如此多的读取,这可能会耗尽熵,您可以改为执行 @indiv suggested in the comments :播种 PRNG 以生成更多种子。好处是你只需要一颗好种子。缺点是它可能让您容易受到 PRNG 缺陷的影响。

这实际上是 /dev/urandom 所做的,它使用 /dev/random 的真正随机性来播种它自己的 PRNG,以确保始终有随机数。你可以从 /dev/urandom 中读取你的种子。好处是这增加了另一个 PRNG,它可以通过使用相同 PRNG 算法的输出为您的 PRNG 播种来消除任何缺陷……或者它可能会使它们变得更糟。缺点是您不知道 /dev/urandom 是如何生成这些种子的,并且它会因平台而异。


任何这些都比使用 timeseed +1, seed + 2, ...

关于c - 播种许多 PRNG,然后不得不再次播种,什么是高质量的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36946553/

相关文章:

c - 当我运行代码时,出现段错误,但是当调试器运行它时,它说没有问题

c - Malloc 中不同操作系统的结果不同

排序 3 个随机数的 C 程序,void reorder3(int a, int *b, int **c);

Java 的 Random 类的 Javascript 实现将使用相同的种子生成相同的序列

c++ - 从字符串中随机选择特定子序列

Java 如何创建一个随机数 mod 5?

c - 数组索引减去字符在 C 中意味着什么?

c - C 中的逻辑运算符导致我的循环出现问题?

TSQL 使用 2 个日期之间的随机值更新日期时间

c - 为什么 "int x = 5; printf("%d %d %d", x==5, x=10, x==5) ;"in C print "0 10 0"?