7

我正在使用 MPICH2 来实现“奇偶”排序。我进行了实现,但是当我将他的值随机分配给每个进程时,相同的数字会随机分配给所有进程。

这是每个进程的代码,每个进程随机化他的值..

int main(int argc,char *argv[])
{
    int  nameLen, numProcs, myID;
    char processorName[MPI_MAX_PROCESSOR_NAME];
    int myValue;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&myID);
    MPI_Comm_size(MPI_COMM_WORLD,&numProcs);    
    MPI_Get_processor_name(processorName,&nameLen);
    MPI_Status status;

    srand((unsigned)time(NULL));
    myValue = rand()%30+1; 

    cout << "myID: " << myID << " value: " << myValue<<endl;
    MPI_Finalize();

    return 0;
 }

为什么每个进程都得到相同的值?

编辑:感谢您的回答:)

我换了行

 srand((unsigned)time(NULL));

 srand((unsigned)time(NULL)+myID*numProcs + nameLen);

它为每个进程提供了不同的值:)

4

2 回答 2

6

这项任务并非微不足道。

你得到相同的数字,因为你srand()用初始化time(0)。什么time(0)是返回当前秒(自纪元以来)。因此,如果所有进程都具有同步时钟,那么只要它们srand()在同一秒调用,所有进程都将使用相同的种子进行初始化,这是很可能的。我什至在大型机器上也观察到了这一点。

解决方案 1. 使用局部值初始化随机种子。

我所做的是在计算随机种子中包含一些与cat /proc/meminfo结合的内存使用情况/dev/random,这对物理机器来说比时钟更本地化。请注意,对于一台机器上的 N 个任务,这可能仍然会失败。但如果我没记错的话,我也用过task_id. 任何本地任务都足够了。结合东西也是个好主意。毕竟,与实际计算相比,这些计算应该非常短。最好保持安全。

解决方案 2. 计算种子作为预处理步骤。

task 0您还可以使用您的方法生成随机种子并使用send-to-all. 但是,在进行大规模(例如 10^5 个进程)时,它可能会遇到扩展问题。您还可以使用任何其他方法来加载参数,并将种子准备为预处理步骤。然而,它也涉及一些不平凡的工作。

于 2013-11-22T09:28:10.867 回答
2

这是因为您的种子没有发生足够的变化,而随机性取决于您的种子。

srand 文档

对于在调用 srand 时使用的每个不同的种子值,可以预期伪随机数生成器在随后调用 rand 时生成不同的连续结果。

编辑:尝试预先生成种子或为每次srand调用手动更改种子。

于 2013-11-22T09:28:21.743 回答