Microsoft MPI 中的死锁 [=v10=]
Deadlock in Microsft MPI MPI_Isend
我有以下 c/c++ Microsoft MPI 代码
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int main (int argc, char *argv[])
{
int err, numtasks, taskid;
int out=0,val;
MPI_Status status;
MPI_Request req;
err=MPI_Init(&argc, &argv);
err=MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
err=MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
int receiver=(taskid+1)% numtasks;
int sender= (taskid-1+numtasks)% numtasks;
printf("sender %d, receiver %d, rank %d\n",sender,receiver, taskid);
val=50;
MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req);
MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req);
printf ("Rank: %d , Value: %d\n", taskid, out );
err=MPI_Finalize();
return 0;
}
如果使用超过 2 个进程启动,应用程序将进入死锁状态。
使用 2 个进程,应用程序可以运行,但不会执行 "out" 上的写入。
此代码适用于 linux mpi 发行版,问题似乎只出现在 Microsoft 版本中。有帮助吗?
首先,每个 MPI 进程执行两次通信:一次发送和一次接收。所以你需要存储两个请求(MPI_Request req[2]
)和两个状态检查(MPI_Status status[2]
)。
其次,您需要在调用 non-blocking send/recvs 之后等待,以确保它们正确完成。
MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req[0]);
MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req[1]);
// While the communication is happening, here you can overlap computation
// on data that is NOT being currently communicated, with the communication of val/out
MPI_Waitall(2, req, status);
// Now both the send and receive have been finished for this process,
// and we can access out, assured that it is valid
printf ("Rank: %d , Value: %d\n", taskid, out);
至于为什么这适用于 Linux 发行版,而不是 Microsoft 发行版...我只能假设 under-the-hood Linux 实施有效实施 non-blocking 通信作为阻塞通信。也就是说,他们 "cheating" 正在为您完成通信,然后才应该完成。这使他们更容易,因为他们不必跟踪有关通信的尽可能多的信息,但它也破坏了您重叠计算和通信的能力。你不应该依赖它来工作。
我有以下 c/c++ Microsoft MPI 代码
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int main (int argc, char *argv[])
{
int err, numtasks, taskid;
int out=0,val;
MPI_Status status;
MPI_Request req;
err=MPI_Init(&argc, &argv);
err=MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
err=MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
int receiver=(taskid+1)% numtasks;
int sender= (taskid-1+numtasks)% numtasks;
printf("sender %d, receiver %d, rank %d\n",sender,receiver, taskid);
val=50;
MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req);
MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req);
printf ("Rank: %d , Value: %d\n", taskid, out );
err=MPI_Finalize();
return 0;
}
如果使用超过 2 个进程启动,应用程序将进入死锁状态。 使用 2 个进程,应用程序可以运行,但不会执行 "out" 上的写入。 此代码适用于 linux mpi 发行版,问题似乎只出现在 Microsoft 版本中。有帮助吗?
首先,每个 MPI 进程执行两次通信:一次发送和一次接收。所以你需要存储两个请求(MPI_Request req[2]
)和两个状态检查(MPI_Status status[2]
)。
其次,您需要在调用 non-blocking send/recvs 之后等待,以确保它们正确完成。
MPI_Isend(&val, 1, MPI_INT, receiver, 1, MPI_COMM_WORLD, &req[0]);
MPI_Irecv(&out, 1, MPI_INT, sender, 1, MPI_COMM_WORLD, &req[1]);
// While the communication is happening, here you can overlap computation
// on data that is NOT being currently communicated, with the communication of val/out
MPI_Waitall(2, req, status);
// Now both the send and receive have been finished for this process,
// and we can access out, assured that it is valid
printf ("Rank: %d , Value: %d\n", taskid, out);
至于为什么这适用于 Linux 发行版,而不是 Microsoft 发行版...我只能假设 under-the-hood Linux 实施有效实施 non-blocking 通信作为阻塞通信。也就是说,他们 "cheating" 正在为您完成通信,然后才应该完成。这使他们更容易,因为他们不必跟踪有关通信的尽可能多的信息,但它也破坏了您重叠计算和通信的能力。你不应该依赖它来工作。