如何使用C ++仅为Open / Microsoft MPI中的某些进程创建关键部分?

问题描述

我是MPI的新手,想了解如何为仅几个正在运行的流程创建关键部分。我知道我可以为所有进程创建这样的文件

for (int i = 0; i < 1000; ++i)
{
    MPI_Barrier(MPI_COMM_WORLD);
    std::cout << "RANK " << rank << " PRINTS " << i << std::endl;
}

但是,如果至少一个进程不会触发MPI_Barrier(),则此操作将不起作用。假设我是这样做的:

if(rank > 0)
for (int i = 0; i < 1000; ++i)
{
    MPI_Barrier(MPI_COMM_WORLD);
    std::cout << "RANK " << rank << " PRINTS " << i << std::endl;
}

这将崩溃,因为第0个进程将跳过循环。那么,如何允许所有其他进程同步打印,并在第0个进程中做其他事情(假设所有打印结束后都等待消息)?

解决方法

正如 @Gilles Gouaillardet 所指出的那样,您可以使用MPI_Comm_split创建不具有等级0的通信器。可以使用此新通信器调用MPI_Barrier来同步其余过程。等级0完成后,可以调用COMM_WORLD上的barrier并等待其余进程对其进行调用。

其余进程(例如1到N)可以通过使用for loop1上的N迭代和{ {1}}块,它基于ifrank执行代码区域,如下面的示例所示。

MPI_Barrier

另一种方法(无需创建新的通信器)是您可以使用环发消息(环广播)的概念。

MPI_Comm_split(MPI_COMM_WORLD,color,key,newcomm) // create new comm without rank 0
if(rank>0) {
  for (int i = 1; i < size; ++i)
   {
    if(rank == i) { // Critical region. Only one rank can enter here at a time. Here it enters sequentially from 0 to size
       std::cout << "RANK " << rank << " PRINTS " << i << std::endl; // After calling Critical Session Part,call barrier to signal other processes.
       MPI_Barrier(newcomm);
    } else {
       MPI_Barrier(newcomm); // all other proesses (except rank == i) should wait and do not enter the critical region
    }
   }
       MPI_Barrier(MPI_COMM_WORLD);// This barrier will be called with rank 0         
} else {
       //do some work for rank 0
       // wait for the rest of the processes
       MPI_Barrier(MPI_COMM_WORLD);         
}

在这里,if (rank == 0) { value = 1; MPI_Send( &value,1,MPI_INT,rank + 1,MPI_COMM_WORLD ); // Do something useful } else { MPI_Recv( &value,rank - 1,MPI_COMM_WORLD,&status ); if (rank < size - 1){ //criticalregion MPI_Send( &value,MPI_COMM_WORLD ); } } MPI_Barrier(MPI_COMM_WORLD); rank 0发送消息,而消息又向rank 1发送,依此类推。这样,进程在接收到消息后可以依次执行代码(关键区域),然后将消息发送到更高级别并触发执行。