mpi阻塞型函数的死锁

来源:互联网 发布:gis制作数据分布地图 编辑:程序博客网 时间:2024/06/01 22:48
 1. 总会死锁的情形
 CALL MPI_COMM_RANK(comm, rank, ierr)
 IF (rank.EQ.0) THEN
  CALL MPI_RECV(recvbuf, count, MPI_REAL, 1, tag, comm, status, ierr)
  CALL MPI_SEND(sendbuf, count, MPI_REAL, 1, tag, comm, ierr)
 ELSE IF( rank .EQ. 1)
  CALL MPI_RECV(recvbuf, count, MPI_REAL, 0, tag, comm, status, ierr)
  CALL MPI_SEND(sendbuf, count, MPI_REAL, 0, tag, comm, ierr)
 END IF
讲解:

  进程0的第一条接收语句A能否完成取决于进程1的第二条发送语句D,即A依赖于D,从执行次序上可以明显地看出,进程0向进程1发送消息的语句C的执行又依赖于它前面的接收语句A的完成,即C依赖于A;同时,进程1的第一条接收语句B能否完成取决于进程0的第二条发送语句C的执行,即B依赖于C,从执行次序上可以明显地看出,向进程0发送消息的语句D的执行又依赖于B的完成,故有A依赖于D,而D又依赖于B,B依赖于C,C依赖于A,形成了一个环,进程0和进程1相互等待,彼此都无法执行下去,必然导致死锁。

图7-1 总会死锁的情形


2.可能死锁的情形
 CALL MPI_COMM_RANK(comm, rank, ierr)
 IF (rank.EQ.0) THEN
  CALL MPI_SEND(sendbuf, count, MPI_REAL, 1, tag, comm, ierr)                                   A
  CALL MPI_RECV(recvbuf, count, MPI_REAL, 1, tag, comm, status, ierr)                     C
 ELSE (rank .EQ.1)
  CALL MPI_SEND(sendbuf, count, MPI_REAK, 0, tag, comm, status, ierr)                    B
  CALL MPI_RECV(recvbuf, count, MPI_REAL, 0, tag, comm, status, ierr)                      D
 END IF


图7-2 可能死锁的情形

  由于进程0或进程1的发送需要系统提供缓冲区(在MPI的四种通信模式中有详细的解释),如果系统缓冲区不足,则进程0或进程1的发送将无法完成,相应的,进程1和进程0的接收也无法正确完成。显然对于需要相互交换数据的进程,直接将两个发送语句写在前面也是不安全的。

说明:当进程0发送的消息长度超过缓冲区大小时,要等到全部消息发送完成函数才能返回,在这种情况下,A的完成依赖于D的成功接收,而D的调用依赖于B的完成,B发送消息要等到C成功接收,而C的调用依赖于A的完成,从而造成彼此依赖,陷入死锁。


3.可以避免死锁的情形
CALL MPI_COMM_RANK(comm, rank, ierr)
IF (rank.EQ.0) THEN
 CALL MPI_SEND(sendbuf, count, MPI_REAL, 1, tag, comm, ierr)
 CALL MPI_RECV(recvbuf, count, MPI_REAL, 1, tag, comm, status, ierr)
ELSE (rank .EQ. 1)
 CALL MPI_RECV(recvbuf, count, MPI_REAL, 0, tag, comm, status, ierr)
 CALL MPI_SEND(sendbuf, count, MPI_REAL, 0, tag, comm, ierr)
END IF 

图7-3 可以避免死锁的情形

C的完成只需要A完成,而A的完成只要有对应的D存在,则不需要系统提供缓冲区也可以进行,这里恰恰满足这样的条件,因此A总能够完成,因此D也一定能完成。当A和D完成后,B的完成只需要相应的C,不需要缓冲区也能完成,因此B和C也一定能完成,所以说这样的通信形式是安全的。显然A和C,D和B同时互换,从原理上说和这种情况是一样的,因此也是安全的。













   


0 0
原创粉丝点击