MPI中每个进程的随机数

时间:2013-11-22 09:25:05

标签: c++ random mpi mpich

我正在使用MPICH2来实现“Odd-Even”排序。 我做了实现但是当我随机化到每个进程他的价值时, 相同的数字随机分配给所有进程。

以下是每个流程的代码,每个流程随机化他的值..

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);

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

2 个答案:

答案 0 :(得分:6)

这项任务并非无足轻重。

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

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

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

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

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

答案 1 :(得分:2)

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

来自srand docs

  

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

编辑:尝试预先生成种子,或者为每{{}}}次呼叫手动更改种子。