MPI_Comm_split 与 MPI_Send / MPI_Recv 的关系

Posted

技术标签:

【中文标题】MPI_Comm_split 与 MPI_Send / MPI_Recv 的关系【英文标题】:The relation between MPI_Comm_split and MPI_Send / MPI_Recv 【发布时间】:2018-05-29 04:15:54 【问题描述】:

假设有 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;

按预期输出“完成”三倍。

但是这段代码有问题(也是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 究竟是什么关系?

【问题讨论】:

【参考方案1】:

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

在您的示例中,等级1 挂在MPI_Recv() 中,因此等级0 上的MPI_Comm_split() 无法完成(并且永远不会调用MPI_Send())并因此出现死锁。

您可以考虑使用padb 来可视化 MPI 程序的状态,这样可以很容易地看到堆栈卡在哪里。

【讨论】:

再一次,你给了我想要的答案。非常感谢。

以上是关于MPI_Comm_split 与 MPI_Send / MPI_Recv 的关系的主要内容,如果未能解决你的问题,请参考以下文章

关于MPI_Send与MPI_Recv语义

MPI_Send() 和 MPI_Ssend() 之间的区别?

MPI_SEND 在 MPI_BARRIER 之后停止工作

MPI_SEND 占用大量虚拟内存

为啥 MPI_SEND 在我的 for 循环中不起作用?如果明确说明它工作正常

使用 MPI_Send 和 MPI_Recv 未正确接收矩阵