MPI_Send 可能会或可能不会阻止。它将阻塞,直到发送方可以重用发送方缓冲区。当缓冲区被发送到较低的通信层时,一些实现将返回给调用者。当另一端有匹配的MPI_Recv() 时,其他一些将返回给调用者。所以这个程序是否会死锁取决于你的 MPI 实现。
由于这个程序在不同的 MPI 实现中表现不同,你可以考虑重写它,这样就不会出现死锁:
MPI_Comm_rank (comm, &my_rank);
if (my_rank == 0) {
MPI_Send (sendbuf, count, MPI_INT, 1, tag, comm);
MPI_Recv (recvbuf, count, MPI_INT, 1, tag, comm, &status);
} else if (my_rank == 1) {
MPI_Recv (recvbuf, count, MPI_INT, 0, tag, comm, &status);
MPI_Send (sendbuf, count, MPI_INT, 0, tag, comm);
}
请始终注意,对于每个 MPI_Send(),必须有一个配对 MPI_Recv(),两者在时间上“平行”。例如,这可能会以死锁告终,因为配对的发送/接收调用没有及时对齐。它们相互交叉:
RANK 0 RANK 1
---------- -------
MPI_Send() --- ---- MPI_Send() |
--- --- |
------ |
-- | TIME
------ |
--- --- |
MPI_Recv() <-- ---> MPI_Recv() v
另一方面,这些进程不会以死锁结束,当然前提是在同一个通信器域中确实有两个等级为 0 和 1 的进程。
RANK 0 RANK 1
---------- -------
MPI_Send() ------------------> MPI_Recv() |
| TIME
|
MPI_Recv() <------------------ MPI_Send() v
如果通信器com 的大小不允许排名1(只有0),上述固定程序可能会失败。这样,if-else 将不会采用else 路由,因此,没有进程会监听MPI_Send(),并且等级 0 将死锁。
如果您需要使用当前的通信布局,那么您可能更愿意使用MPI_Isend() 或MPI_Issend() 来代替非阻塞发送,从而避免死锁。