OpenMPI MPI_Send 与英特尔 MPI MPI_Send
OpenMPI MPI_Send vs Intel MPI MPI_Send
我有一段代码,我使用 openmpi 编译并 运行。最近,我想 运行 使用 Intel MPI 编写相同的代码。但是我的代码没有按预期工作。
我深入研究了代码,发现 MPI_Send 在两个实现中的行为不同。
我从不同的论坛得到建议使用 MPI_Isend 而不是来自不同论坛的 MPi_Send。但这需要大量工作来修改代码。英特尔 MPI 中是否有任何变通方法可以使其像在 OpenMPI 中一样工作。可能是一些标志或增加缓冲区或其他东西。预先感谢您的回答。
int main(int argc, char **argv) {
int numRanks;
int rank;
char cmd[] = "Hello world";
MPI_Status status;
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD, &numRanks);
MPI_Comm_rank (MPI_COMM_WORLD, &rank);
if(rank == 0) {
for (int i=0; i< numRanks; i++) {
printf("Calling MPI_Send() from rank %d to %d\n", rank, i);
MPI_Send(&cmd,sizeof(cmd),MPI_CHAR,i,MPI_TAG,MPI_COMM_WORLD);
printf("Returned from MPI_Send()\n");
}
}
MPI_Recv(&cmd,sizeof(cmd),MPI_CHAR,0,MPI_TAG,MPI_COMM_WORLD,&status);
printf("%d receieved from 0 %s\n", rank, cmd);
MPI_Finalize();
}
OpenMPI 结果
# mpirun --allow-run-as-root -n 2 helloworld_openmpi
Calling MPI_Send() from rank 0 to 0
Returned from MPI_Send()
Calling MPI_Send() from rank 0 to 1
Returned from MPI_Send()
0 receieved from 0 Hello world
1 receieved from 0 Hello world
英特尔 MPI 结果
# mpiexec.hydra -n 2 /root/helloworld_intel
Calling MPI_Send() from rank 0 to 0
停留在 MPI_Send。
假设 MPI_Send()
会 return 在匹配的接收被发布之前是不正确的,所以你的代码在 MPI 标准方面是不正确的,你很幸运它没有挂起 Open MPI.
MPI 实现通常急于发送 small 消息,因此 MPI_Send()
可以 return 立即发送,但这是标准未强制要求的实现选择,并且"small" 消息取决于库版本、您使用的互连和其他因素。
此处唯一安全且可移植的选择是编写正确的代码。
FWIW,MPI_Bcast(cmd, ...)
更适合这里,假设所有等级都已经知道字符串长度加上 NUL 终止符。
最后但同样重要的是,缓冲区参数是 cmd
而不是 &cmd
。
我有一段代码,我使用 openmpi 编译并 运行。最近,我想 运行 使用 Intel MPI 编写相同的代码。但是我的代码没有按预期工作。 我深入研究了代码,发现 MPI_Send 在两个实现中的行为不同。
我从不同的论坛得到建议使用 MPI_Isend 而不是来自不同论坛的 MPi_Send。但这需要大量工作来修改代码。英特尔 MPI 中是否有任何变通方法可以使其像在 OpenMPI 中一样工作。可能是一些标志或增加缓冲区或其他东西。预先感谢您的回答。
int main(int argc, char **argv) {
int numRanks;
int rank;
char cmd[] = "Hello world";
MPI_Status status;
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD, &numRanks);
MPI_Comm_rank (MPI_COMM_WORLD, &rank);
if(rank == 0) {
for (int i=0; i< numRanks; i++) {
printf("Calling MPI_Send() from rank %d to %d\n", rank, i);
MPI_Send(&cmd,sizeof(cmd),MPI_CHAR,i,MPI_TAG,MPI_COMM_WORLD);
printf("Returned from MPI_Send()\n");
}
}
MPI_Recv(&cmd,sizeof(cmd),MPI_CHAR,0,MPI_TAG,MPI_COMM_WORLD,&status);
printf("%d receieved from 0 %s\n", rank, cmd);
MPI_Finalize();
}
OpenMPI 结果
# mpirun --allow-run-as-root -n 2 helloworld_openmpi
Calling MPI_Send() from rank 0 to 0
Returned from MPI_Send()
Calling MPI_Send() from rank 0 to 1
Returned from MPI_Send()
0 receieved from 0 Hello world
1 receieved from 0 Hello world
英特尔 MPI 结果
# mpiexec.hydra -n 2 /root/helloworld_intel
Calling MPI_Send() from rank 0 to 0
停留在 MPI_Send。
假设 MPI_Send()
会 return 在匹配的接收被发布之前是不正确的,所以你的代码在 MPI 标准方面是不正确的,你很幸运它没有挂起 Open MPI.
MPI 实现通常急于发送 small 消息,因此 MPI_Send()
可以 return 立即发送,但这是标准未强制要求的实现选择,并且"small" 消息取决于库版本、您使用的互连和其他因素。
此处唯一安全且可移植的选择是编写正确的代码。
FWIW,MPI_Bcast(cmd, ...)
更适合这里,假设所有等级都已经知道字符串长度加上 NUL 终止符。
最后但同样重要的是,缓冲区参数是 cmd
而不是 &cmd
。