MPI_Comm_split和MPI_Send/MPI_Recv的关系

The relation between MPI_Comm_split and MPI_Send / MPI_Recv

假设有 3 个进程,这段代码工作正常:

#include <iostream>
#include <mpi.h>
using namespace std;

int main(){

    MPI_Init(NULL, NULL);

    int rank; MPI_Comm SubWorld; int buf;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0){
        MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);
        MPI_Send(&buf, 1, MPI_INT, 1, 55, MPI_COMM_WORLD);
    }
    else if (rank == 1){
        MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);
        MPI_Recv(&buf, 1, MPI_INT, 0, 55, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }
    else MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);

    cout << "Done" << endl;

    MPI_Finalize();

    return 0;
}

输出 "Done" 预期的三倍。

但是这段代码有问题(也是3个进程):

#include <iostream>
#include <mpi.h>
using namespace std;

int main(){

    MPI_Init(NULL, NULL);

    int rank; MPI_Comm SubWorld; int buf;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0){
        MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);
        MPI_Send(&buf, 1, MPI_INT, 1, 55, MPI_COMM_WORLD);
    }
    else if (rank == 1){
        MPI_Recv(&buf, 1, MPI_INT, 0, 55, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);
    }
    else MPI_Comm_split(MPI_COMM_WORLD, rank, rank, &SubWorld);

    cout << "Done" << endl;

    MPI_Finalize();

    return 0;
}

没有输出!!

MPI_Comm_split和MPI_Send/MPI_Recv到底是什么关系导致了这个问题?

MPI_Comm_split()是一个集体操作,这意味着来自初始通信器的所有MPI任务(例如这里的MPI_COMM_WORLD)必须同时调用它。

在您的示例中,等级 1MPI_Recv() 中挂起,因此等级 0 上的 MPI_Comm_split() 无法完成(并且永远不会调用 MPI_Send())因此陷入僵局。

您可能会考虑 padb 以可视化 MPI 程序的状态,这样可以很容易地看到堆栈卡在何处。