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
)必须同时调用它。
在您的示例中,等级 1
在 MPI_Recv()
中挂起,因此等级 0
上的 MPI_Comm_split()
无法完成(并且永远不会调用 MPI_Send()
)因此陷入僵局。
您可能会考虑 padb
以可视化 MPI 程序的状态,这样可以很容易地看到堆栈卡在何处。
假设有 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
)必须同时调用它。
在您的示例中,等级 1
在 MPI_Recv()
中挂起,因此等级 0
上的 MPI_Comm_split()
无法完成(并且永远不会调用 MPI_Send()
)因此陷入僵局。
您可能会考虑 padb
以可视化 MPI 程序的状态,这样可以很容易地看到堆栈卡在何处。