3.5 点对点通信的语义 BACKWARDFORWARD


在这节描述点对点通信, 一个有效的MPI实现保证它的一般特性。

Order 消息是“非超过的”:如果一个发送者给同一目的连续发送两个消息,,并且匹配同一接收,而且如果第一个消息仍挂起,那么这个接手操作不能接收第二个消息。如果一个接收者连续登入两个接收并匹配同一消息,而且如果第一个接收仍挂起,那么这个消息不能完成第二个接收操作。这要求发送到接收的匹配设施。如果进程是单线索的,并且不使用任意值MPI_ANY_SOURCE的接收,那么它保证消息传送代码是确定的。(后面描述的一些调用, 例如:MPI_CANCEL或MPI_WAITANY, 是非确定性的附加源)。   

如果一个进程是单线索执行的,那么这个进成执行的任何两个通信是排序的。另一方面,如果进程是多线索的,那么线索执行的语义在由两个不同线索执行的两个发送操作之间可以不定义相对顺序。既使物理上一操作先于另一个,逻辑上操作是并发的。这时,被发送的两个消息以任何顺序被接收。类似地,如果逻辑上是并发的两个接收操作连续接收两个被发送的消息,那么这两个消息能在顺序上匹配被接收的两个消息。

例子3.5 一个“非超过的”消息例子。

CALL MPI_COMM_RANK(comm, rank, ierr)

IF (rank.EQ.0) THEN
 CALL MPI_BSEND(buf1, count, MPI_REAL, 1, tag, comm, ierr)
 CALL MPI_BSEND(buf2, count, MPI_REAL, 1, tag, comm, ierr)
ELSE ! rank.EQ.1
 CALL MPI_RECV(buf1, count, MPI_REAL, 0, MPI_ANY_TAG, comm, status, ierr)
 CALL MPI_RECV(buf2, count, MPI_REAL, 0, tag, comm, status, ierr)
END IF

由第一个发送者发送的消息必须被第一个接收者接收, 而由第二个发送者发送者发送的消息必须被第二个接收者接收。

Progress 如果一对匹配的发送和接收已被在两个进程上初始化, 那么至少这两个操作之一将独立于系统的其他动作而完成: 除非接收被另一个消息满足并完成, 这个发送操作将完成; 除非在同一目标进程登入的另一匹配进程使用这个发送的消息,这个接收操作将完成。

例子3.6 混在一起的匹配的一对发送和接收。

CALL MPI_COMM_RANK(comm, rank, ierr)
IF (rank.EQ.0) THEN
 CALL MPI_BSEND(buf1, count, MPI_REAL, 1, tag1, comm, ierr)
 CALL MPI_SSEND(buf2, count, MPI_REAL, 1, tag2, comm, ierr)
ELSE ! rank.EQ.1
 CALL MPI_RECV(buf1, count, MPI_REAL, 0, tag2, comm, status, ierr)
 CALL MPI_RECV(buf2, count, MPI_REAL, 0, tag1, comm, status, ierr)
END IF

两进程首先引用他们的第一个通信调用。因为进程0的第一个发送使用缓存模式, 所以无论进程1的状态如何, 它必须完成。因为没有匹配接收登入,消息将被拷贝到缓存空间。(如果得不到足够的缓存空间, 那么程序将失败。)然后引用第二个发送。在这点,使发送和接收操作匹配,两操作必须完成。进程1引用它的第二个接收调用,这个调用将被缓存的消息满足。注意,进程1以消息发送的相反顺序接收消息。

Fairness MPI不保证通信处理中的公正性。假设一个发送被登入。则目标进程可能重复登入匹配这个发送的接收,但仍没有接收这个消息,因为每次被另一个发送的消息超过。类似地,假设一个多线索登入一个接收。那么匹配这个接收的消息可能被重复接收,但仍没有满足这个接收,因为它被这个结点登入的其他接收超过(其他执行线索)。这种情况下,由用户负责阻止。

Resource limitations( 资源限制 )任何挂起的通信操作使用有限的系统资源。当缺少资源而阻止一个MPI调用执行时, 可能发生错误。一个高质量实现给“准备好模式”或“同步模式”的每个挂起发送,给每个挂起接收使用(小的)定数资源。但是,缓存空间用于存储标准模式发送的消息,并且当得不到匹配接收时,必须用于存储以缓存模式发送的消息。在许多系统中,缓存得到的空间将远远小于程序数据存储空间。那么,容易编写超出可得缓存空间的程序。   

MPI允许用户给以缓存模式发送的消息提供缓存空间。MPI也为这个缓存的使用指定详细的操作模型。要求一个MPI实现不比这个模型更坏。当用户使用缓存发送时,这使他们避免缓存溢出。在3.6节描述缓存的分配和使用。   

由于缺少缓存空间而不能完成的一个缓存发送操作是错误的。当检测到这种情况时,可引起程序非正常结束的一个错误被通知。另一方面,由于缺少缓存空间而不能完成的一个标准发送将阻塞,等待缓存空间空出或一个匹配接收登入。在许多情况下,这个动作是受欢迎的。考虑这样一种情况,一个生产者重复生产新值并把他们发送给一个使用者。假设生产者产生值比使用者使用的快。如果使用缓存发送,将导致一个缓存溢出。给这个程序加一个附加的同步以阻止这种情况发生。如果使用标准发送,那么生产者将被自动停止,就象当缓存空间得不到时,它的发送操作将阻止。   

有些情况,缺少缓存空间导致死索情况。由下面的例子解释。

例子3.7 一个消息的交换。

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

既使得不到数据缓存空间, 这个程序将成功。在这个例子中,用一个同步发送替代这个标准发送操作。

例子3.8 打算交换消息。

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 ! 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

第一个进程的接收操作必须在它的发送以前完成, 并只要第二个进程的匹配发送操作被执行, 就能完成。第二个进程的接收操作必须在它的发送以前完成,并只要第一个进程的匹配发送被执行,就能完成。这个程序将总是死锁。其他的发送模式也是一样。

例子3.9 依赖缓存的一个交换。

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_SEND(sendbuf, count, MPI_REAK, 0, tag, comm, status, ierr)
END IF

由每个进程发送的消息必须在发送操作返回以前和接收操作开始以前被拷贝出来。为完成这个程序,至少被发送的两个消息之一必须被缓存。所以,只要通信系统至少缓存count个数据, 这个程序就能成功。   


Copyright: NPACT
BACKWARDFORWARD