如何避免重复的随机数生成?

Pla*_*ong 0 shell c++ random parallelism

长话短说

程序同时启动两次时会抽取相同的随机种子。它是怎么发生的?

细节

我正在运行 MCMC 统计分析,因此我执行程序 (phylobayes) 两次以获得2 个独立的重复。

为此,我的 shell 脚本分离每个复制运行,如下所示(示意性地):

pb -d "inputdata" "replicate1" &
pid1=$!

pb -d "inputdata" "replicate2" &
pid2=$!

wait "$pid1"
wait "$pid2"
Run Code Online (Sandbox Code Playgroud)

(然后,使用 slurm 将这个脚本提交到计算集群(Debian 10))sbatch

但我的许多运行(例如 30%)都是从相同的随机种子开始的!如日志文件所示。

Phylobayes使用 C++Random::initRandom()命令。[编辑:实际上,正如指出的那样,该函数在包内有一个自定义定义]。

从技术上讲,是否可以采用相同的随机种子?它使用 /dev/random 还是 /dev/urandom ?

sleep如果是,我将在开始之间插入一个命令;

如果没有,我必须明白我犯了什么愚蠢的错误,但我不知道它会是什么......

und*_*cat 5

\n

从技术上讲,是否可以采用相同的随机种子?

\n
\n

如果您查看链接的函数,您会发现它使用微秒数作为种子(模 10^6):

\n
void Random::InitRandom(int seed)   {\n\n    if (seed == -1) {\n        struct timeval tod;\n        gettimeofday(&tod, NULL);\n        seed = tod.tv_usec; // <== this line\n    }\n    Seed = seed;\n    srand(seed);\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

所以,是的,如果您的软件的两个实例在同一微秒内运行该函数(或者可能恰好有 1 秒的差异等),您将获得相同的种子。这是合理的,因为您会立即启动一个实例。

\n

gettimeofday() 的粒度通常比 1 \xce\xbcs 更粗,因此时间上彼此非常接近的运行可能具有相同的 tv_usec 值,即使它们没有发生在精确的时间上同样的微秒。

\n

我认为解决此问题的最佳方法是使用适合您使用软件的方式的不同种子初始化算法来构建您自己的版本。例如,您可以在每次后续运行中将种子数增加 1,或者使用 /dev/random,而不是使用微秒。

\n

或者,如果您有 GNU coreutils,则可以使用该sleep 0.001命令将第二次执行暂停 1 毫秒,这应该会引入足以让不同实例具有不同种子的延迟。

\n