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相互等待,彼此都無法執行下去,必然導致死鎖。
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
由於進程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
C的完成只需要A完成,而A的完成只要有對應的D存在,則不需要系統提供緩衝區也可以進行,這裏恰恰滿足這樣的條件,因此A總能夠完成,因此D也一定能完成。當A和D完成後,B的完成只需要相應的C,不需要緩衝區也能完成,因此B和C也一定能完成,所以說這樣的通信形式是安全的。顯然A和C,D和B同時互換,從原理上說和這種情況是一樣的,因此也是安全的。
,