MPI 发送消息或将其作为参数提供

MPI sending messages or giving them as parameter

本文关键字:参数 消息 MPI      更新时间:2023-10-16

我有一个带有一个管理器和多个工作人员的 MPI 实现。main函数位于名为 run_mpi.cpp 的文件中。它进行 MPI 的初始化并调用 manager.cppworker.cpp 。我想在worker.cpp中有一些变量。我有两种方法可以做到这一点:

  1. main 函数在 run_mpi.cpp 中调用它时,我可以将变量作为参数提供给worker.cpp

  2. 我可以在manager.cpp中发送带有MPI_SendMPI_Isend的变量。

我可以在什么条件下使用它们?它们有什么好处?

您需要将

两者视为完全独立的程序。 MPI 在程序的实例(秩(之间提供通信层,但它们之间没有共享数据。 假设您的主节点读取一个包含数字列表的文件,将每个数字发送给工作人员,然后工作人员对该数字执行某些操作。 你可能会有这样的东西:

float localx;
float *x;
int rank;
int size;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,rank);
MPI_Comm_size(MPI_COMM_WORLD,size);
x=new float[size];
if (rank==0)
{
  /* Typically, rank 0 is considered the master rank in a master/worker setup
     Open, read, and close file.
     Assume the data is read into array x, which is single precision floating point.
     For ease of illustration, I'm sending to one rank at a time, but this
     is better accomplished using MPI_Scatter. */
  localx=x[0];
  for (int i=1; i<size; i++)
  {
    MPI_Send(&x[i], 1, MPI_FLOAT, i, i, MPI_COMM_WORLD);
  }
  master(localx); // The master subroutine does whatever it needs to do
} else
{
  // If the rank isn't 0, then the rank is a worker
  MPI_Recv(&localx, 1, MPI_FLOAT, 0, rank, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  worker(localx);
}
delete[] x;

前三个 MPI 调用将初始化 MPI 通信环境 (MPI_Init(,获取当前实例的排名号 (MPI_Comm_rank( 和通信器的大小 (MPI_Comm_size(。 MPI_COMM_WORLD的大小是你用mpirun发起的等级。 接下来,分配 x 为每个工作线程保存一个值。

通常,如果您使用的是主/辅助角色模型,则等级 0 将被视为主等级。 因此,如果排名编号为 0,我们将继续读取文件。 作为旁注,除非您使用的是 MPI I/O 或其他并行 I/O,否则只有一个等级访问文件会更安全。 主节点将读取该文件,对于我的示例,该文件的每个工作线程等级应该有一个值。 正如我在评论中所说,使用 MPI_Scatter 是一种更好的方法,但如果您是 MPI 的新手,我们现在将坚持使用基础知识。 首先,我将 localx 设置为 x[0]。 然后,我为每个等级调用MPI_Send一次,向每个等级发送一个 x 元素。 一旦数据被发送出去,主级就可以调用master(localx(并在那里做任何需要做的事情。

如果等级编号不为 0,则等级为工作人员。 工作人员不会读取该文件。 相反,他们将调用MPI_Recv以获取从主服务器发送的数据。 工人队伍将简单地坐在这里等待,直到数据到达。 完成此操作后,工人将调用worker(localx(并在那里执行任何操作。

我见过人们在学习 MPI 时遇到的一大障碍是每个等级的记忆是分开的。 与线程不同,绝对没有共享内存(您的应用程序可以看到,MPI 实现可能会为自己设置一些东西(。 通过分配点,没有一个等级为局部 x 或 x 设置任何值。 主人读完之后,只有主人知道 x 包含什么。 发送数据后,每个工人等级将有一个来自 x 的单个值存储在 localx 中的主节点。

我提到使用MPI_Scatter更好。 这是如何完成的。 条件块之前和之后的所有内容都将保持不变。 条件块将变为:

if (rank==0)
{
  // Read the file, fill x
}
MPI_Scatter(&x[0], size, MPI_FLOAT, &localx, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);
if (rank==0)
{
  master(localx);
} else
{
  worker(localx);
}

不同之处在于,现在,我们不是为每个工人等级发送和接收一次,而是一次将数组分散到每个等级中的变量。 根据您正在执行的操作,可能无法使用MPI_Scatter。 此示例非常简单,您可以。