我知道在以下情况下会发生死锁:
有一件事是等待另一件事来完成它的工作,而另一件事是等待第一件事完成。
这是我的代码:
MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */
if( myrank == 0 ) {
MPI_Recv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );
MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );
}
else if( myrank == 1 ) {
MPI_Recv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );
MPI_Send( a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );
}
在文章Deadlock with 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_Send (sendbuf, count, MPI_INT, 0, tag, comm);
MPI_Recv (recvbuf, count, MPI_INT, 0, tag, comm, &status);
}
嗯,该程序可能会冻结,但其情况并未被视为死锁情况。如果我们认为它是一个死锁情况,那么下面的情况呢:
MPI_Recv (recvbuf, count, MPI_INT, 1, tag, comm, &status);
该计划也将冻结。我写了一篇关于死锁情况的文章,我很困惑。
答案 0 :(得分:0)
无论如何,你的第一段代码都将陷入僵局。
第二个代码块的行为取决于许多因素,例如MPI实现,消息大小和MPI运行时配置。这里的基本思想是阻塞MPI_Send例程只有在可以安全地覆盖发送缓冲区时才会返回。离开发送缓冲区的数据可以直接进入目标进程,也可以复制到某个中间缓冲区空间。如果前者是真的,你的代码就会死锁。否则,您的代码可能看起来效果不错,但在将代码移植到其他系统时可能会遇到问题。
与MPI的僵局'你提到的文章很好地解释了这一点。它还提供了两种避免死锁的解决方案:(1)改变发送和接收的顺序; (2)使用非块发送和接收。实际上有第三种方法可以避免死锁:你可以使用MPI_Sendrecv,这实际上是一个组合的发送和接收调用,保证不会死锁。