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_Ssend() 之间的区别?