在带有MPI的c++代码中,每个进程的随机数相同

The same random numbers for each process in c++ code with MPI

本文关键字:进程 随机数 MPI c++ 代码      更新时间:2023-10-16

我有C++MPI代码,它可以编译并在指定数量的处理器上启动(n)。问题是,它只是简单地执行相同的计算n次,而不是更快地执行一次n

我在各种网站上发现了不少例子,似乎我没有正确使用MPI_Send和MPI_Receive,但我找不到这些命令以函数为输入的实例(我很困惑为什么这些MPI命令对函数以外的任何东西都有用)。

我的代码在下面。从本质上讲,它调用了我编写的一个C++函数来获得Fisher精确测试p值。随机数比特只是我用来测试速度的东西。

我想让这个程序把每组随机变量(即ABCD)的Fisher.TwoTailed分配给不同的处理器,而不是在多个处理器上进行完全相同的计算。提前感谢您的真知灼见——干杯!

这是代码:

int 
main (int argc, char* argv[]) 
{ 
  int id;
  int p;
//
//  Initialize MPI.
//
  MPI::Init ( argc, argv );
//
//  Get the number of processors.
//
  p = MPI::COMM_WORLD.Get_size ( );
//
//  Get the rank of this processor.
//
 id = MPI::COMM_WORLD.Get_rank ( );
  FishersExactTest Fishers;
  int i = 0;
  while (i < 10) {
    int A = 0 + rand() % (100 - 0);
    int B = 0 + rand() % (100 - 0);
    int C = 0 + rand() % (100 - 0);
    int D = 0 + rand() % (100 - 0); 
    cout << Fishers.TwoTailed(A, B, C, D) << endl;
    i += 1;
  }
  MPI::Finalize ( );
  return 0;
}

您应该了解一些关于并行计算和MPI的基本培训。教我基础知识的一个好资源是国家超级计算应用中心(NCSA)提供的一套免费在线课程。

您必须告诉MPI如何并行化代码——它不会自动执行。

换句话说,您不能在所有系统上初始化MPI,然后将它们传递给同一个循环。您希望使用每个处理器的id来确定它将处理循环的哪个部分。然后您需要它们将结果全部传递回ID 0。

以上所有答案都是完全正确的。让我补充一点:

在这里,由于看起来你只是在进行随机采样,所以你所要做的就是让不同的处理器生成不同的随机数,并将其提供给Fishers

int 
main (int argc, char* argv[]) 
{ 
  int id;
  int p;
//
//  Initialize MPI.
//
  MPI::Init ( argc, argv );
//
//  Get the number of processors.
//
  p = MPI::COMM_WORLD.Get_size ( );
//
//  Get the rank of this processor.
//
 id = MPI::COMM_WORLD.Get_rank ( );
  FishersExactTest Fishers;
  srand(id);  // <--- each rank gets a different seed
  int i = 0;
  while (i < 10) {
    int A = 0 + rand() % (100 - 0);
    int B = 0 + rand() % (100 - 0);
    int C = 0 + rand() % (100 - 0);
    int D = 0 + rand() % (100 - 0); 
    cout << Fishers.TwoTailed(A, B, C, D) << endl;
    i += 1;
  }
  MPI::Finalize ( );
  return 0;
}

因为循环是从1..10开始的,所以你仍然会让每个过程做10个样本。如果你想让他们总共10,你可以把10除以p,然后做一些事情来分配剩余的:例如

int niters = (10+id)/p;
int i=0;
while (i < niters) {
  ...
}

那么,运行MPI作业时会收到哪些消息?为了重申其他人所说的,你必须明确定义每个处理器的工作是什么……例如。。如果您的排名为0(默认值),请执行此操作。。。如果您是排名1,依此类推..(或其他语法),定义每个排名的角色。然后,根据您的代码结构,您可以拥有Send/Recv、Gather、Scatter等节点。