【发布时间】:2010-04-04 17:32:05
【问题描述】:
好吧,这真的很奇怪。
我有一个 MPI 程序,其中每个进程都必须生成固定范围内的随机数(范围是从文件中读取的)。发生的情况是,即使我为每个进程设置不同的值,并且rand() 生成的数字在每个进程中不同,生成随机数的表达式仍然会在它们之间产生相同的序列。
以下是所有相关代码:
// 'rank' will be unique for each process
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// seed the RNG with a different value for each process
srand(time(NULL) + rank);
// print some random numbers to see if we get a unique sequence in each process
// 'log' is a uniquely named file, each process has its own
log << rand() << " " << rand() << " " << rand() << std::endl;
// do boring deterministic stuff
while (true)
{
// waitTimeMin and waitTimeMax are integers, Max is always greater than Min
waitSecs = waitTimeMin + rand() % (waitTimeMax - waitTimeMin);
log << "waiting " << waitSecs << " seconds" << std::endl;
sleep(waitSecs);
// do more boring deterministic stuff
}
这是每个进程的输出,有 3 个进程生成 [1,9] 范围内的数字。
流程1:
15190 28284 3149
waiting 6 seconds
waiting 8 seconds
waiting 9 seconds
waiting 4 seconds
过程 2:
286 6264 3153
waiting 6 seconds
waiting 8 seconds
waiting 9 seconds
waiting 4 seconds
过程 3:
18151 17013 3156
waiting 6 seconds
waiting 8 seconds
waiting 9 seconds
waiting 4 seconds
因此,虽然rand() 显然生成了不同的数字,但计算waitSecs 的表达式在所有进程上仍然计算为相同的序列。更奇怪的是:如果我再次使用相同的参数运行程序,只有前 3 个随机数会改变,其余的“随机”序列在每次运行中都会完全一样!改变数字的范围显然会产生与这个不同的结果,但相同的参数总是产生相同的序列,在进程之间和在执行之间:除了前 3 个数字。
这到底是怎么回事?
编辑:所以只是为了看看它是否是简单的随机生成和/或低范围,我用这行替换了随机生成:
waitSecs = waitTimeMin + (int)((double)rand() / ((double)RAND_MAX + 1) * (waitTimeMax - waitTimeMin));
并开始生成 [1,99] 范围内的数字。结果如下:
流程1:
7833 3798 10977
waiting 1 seconds
waiting 20 seconds
waiting 58 seconds
waiting 35 seconds
waiting 82 seconds
waiting 18 seconds
过程 2:
25697 14547 10980
waiting 1 seconds
waiting 20 seconds
waiting 58 seconds
waiting 35 seconds
waiting 82 seconds
waiting 18 seconds
过程 3:
10794 25295 10984
waiting 1 seconds
waiting 20 seconds
waiting 58 seconds
waiting 35 seconds
waiting 82 seconds
waiting 18 seconds
同样的事情。这还是rand()很糟糕吗?
EDIT2:生成从 1 到 10000 的数字时也是如此。
【问题讨论】:
-
检查是否真的是 rand() 问题: log
-
在每种情况下打印您正在播种 srand() 的值。
-
那是 Neil:进程 1 是 X,进程 2 是 X+1,进程 3 是 X+2 等等。
-
您的新公式(从 EDIT1 开始)看起来是正确的。您能否更改循环内的输出语句,同时将
rank的值和用于计算waitSecs的rand()的值提供给我们?