3.8 检查(probe)和取消(cancel) |
MPI_PROBE和MPI_IPROBE操作允许在没有实际收到输入消息的情况下对其进行检查。用户于是可以根据这次返回的信息决定如何接收他们(该信息一般用status返回)。另外,用户可以根据被检查消息的长度分配结束缓冲区大小。
MPI_CANCEL操作允许取消即将来临的通信。在清理(cleanup)的时候往往会有这种要求。发出一个发送或接收将占用户资源(收发缓冲区),因此会用到取消命令来释放这些资源。
MPI_IPROBE(source,tag,comm,flag,status)
IN source source序列,或MPI_ANY_SOURCE(integer)
IN tag tag值,或MPI_ANY_TAG(integer)
IN comm 通信子(句柄)
OUT flag (逻辑)
OUT status 状态目标
int MPI_Iprobe(int source,int tag,MPI_Comm comm,int *flag, MPI_Status *status)
MPI_IPROBE(SOURCE,TAG,COMM,FLAG,STATUS,TERROR)
LOGICAL FLAG
INTEGER SOURCE,TAG,COMM,STATUS(MPI_STATUS_SIZE),IERROR
当存在一个消息可被接收并且MPI_IPROBE(source,tag,comm,flag,status)和参数source,tag,comm相匹配时, 它返回flag=true。 该调用和程序中同一点执行的MPI_RECV(...,source,tag,cmm,status)所收到的消息进行匹配,用status返回和MPI_RECV()同样的返回值。否则该调用返回flag=false并且不对status定义。
如果MPI_IPROBE返回flag=true,则状态目标(status object)能够按3.2.5所描述的方法获取source,tag和检查消息的长度.
使用同样上下文的后绪接收和MPI_IPROBE在status中返回的source和tag将收到和检查相匹配的消息,如果在检查之后没有发生其它插入的接收的话。如果接收过程是多线索的,则用户需要自己确保最后状态不丢失。
MPI_PROBE的source参数可以是MPI_ANY_SOURCE,tag参数可以是MPI_ANY_TAG,以便用户可以检查来自不确定source的消息和/或不确定的tag。不过,一个指明的通信上下文必须提供comm参数。
一个消息被检查后并不一定会被立即接收,同样,一个消息在被接收以前可能会被检查多次。
MPI_PROBE (source,tag,cmm,status)
IN source source序列或MPI_ANY_SOURCE(integer)
IN tag tag值或MPI_ANY_TAG(integer)
IN comm 通信子
OUT status 状态目标
int MPI_Probe(int source,int tag,MPI_Comm comm,MPI_Status *status)
MPI_PROBE(SOURCE,TAG,COMM,STATUS,IERROR)
INTEGER SOURCE,TAG,COMM,STATUS(MPI_STATUS_SIZE),IERROR
MPI_PROBEHE和MPI_IPROBE相似,只是它是一个阻塞调用,只有找到一个匹配调用之后才会返回.
MPI_PROBE和MPI_IPROBE的执行需要进度保证:如果一个进程调用了一个MPI_PROBE,并且一个和检查匹配的发送已被某些进程,则MPI_PROBE调用将返回,除非该消息被另一个同时运行的接收操作所取走(这个操作是被另一个处于检查过程中的线索执行的)。类似地,如果一个进程处于等待MPI_IPROBE状态并且已经处理了匹配消息,则MPI_IPROBE最终将返回flag=true,除非该消息被另一个同时发生的接收操作收走。
例 3.16 使用阻塞检查等待接收消息
CALL MPI_COMM_RANK(comm,rank,ierr)
IF (rank.EQ.) THEN
CALL MPI_SEND(i,1,MPI_INTEGER,2,0,comm,ierr)
ELSE IF(rank.EQ.1) THEN
CALL MPI_SEND(x,1,MPI_REAL,2,0,comm,ierr)
ELSE ! rank.EQ.2
DO i=1,2
CALL MPI_PROBE(MPI_ANY_SOURCE,0, comm,status,ierr)
IF (status(MPI_SOURCE) = 0) THEN
100 CALL MPI_RECV(i,1,MPI_INTEGER,0,0,status,ierr)
ELSE
200 CALL MPI_RECV(x,1,MPI_REAL,1,0,status,ierr)
END IF
END DO
END IF
每个消息都被以正常类型接收。
例 3.17 和上例相似的程序,含有一个错误。
CALL MPI_COMM_RANK(comm,rank,ierr)
IF (rank.EQ.0) THEN
CALL MPI_SEND(i,1,MPI_INTEGER,2,0,comm,ierr)
ELSE IF(rank.EQ.1) THEN
CALL MPI_SEND(x,1,MPI_REAL,2,0,comm,ierr)
ELSE
DO i=1,2
CALL MPI_PROBE(MPI_ANY_SOURCE,0 comm,status,ierr)
IF (status(MPI_SOURCE)=0) THEN
100 CALL MPI_RECV(i,1,MPI_INTEGER,MPI_ANY_SOURCE 0,status,ierr)
ELSE
200 CALL MPI_RECV(x,1,MPI_REAL,MPI_ANY_SOURCE, 0,status,ierr)
END IF
END DO
END IF
我们对例3.16做了很小的改变,用MPI_ANY_SOURCE作为语句100和200两个接收调用语句的source参数。程序这是就出现了错误:接收操作收到的消息可能和前面调用的MPI_PROBE检查的消息不一致。
##建议##
一个MPI_PROBE(source,tag,cmm,status)调用将和同一点执行的MPI_RECV(..., source, tag, comm, status)收到的消息相匹配。假设该消息是source s, tag t和通信子(communicator) c。如果检查调用的tag参数值为MPI_ANY_TAG,则检查的消息将是来自sources的以c 为通信子,tag任意的最早的消息。 在任何情况下检查的消息都是从source s,带着通信子c和tag t的最早消息。这个消息将保持其最早状态直到它被接收。一个使用同样的通信子 及source和tag值的检查的后绪接收操作必须接收该消息,除非它以被其它接收操作收到。
MPI_CANCEL(request)
IN request 通信请求(句柄)
int MPI_Cancel(MPI_Request *request)
MPI_CANCEL(REQUEST,IERROR)
INTEGER REQUEST,IERROR
MPI_CANCEL调用标记取消一个将要发生的非阻塞的通信操作(发送或接收).取消调用是本地的。它立即返回,可能返回时通信还未被真正取消。要完成一个被标记为取消的通信,还需要调用MPI_REQUEST_FREE,MPI_WAIT或MPI_TEST(或any of the derived operations).
如果一个通信被标记为取消,该通信的MPI_WAIT调用不管其它进程的状态如何都将保证返回(MPI_WAIT就象一个本地调用);类似地,如果MPI_TEST在一个忙的等待循环中不断对一个被取消的通信调用MPI_TEST,则MPI_TEST最终将成功。
MPI_CANCEL可以用于取消一个使用坚持请求(见3.9)的通信,用同样的办法它也可以用于非坚持请求。一个成功的取消操作取消激活的通信,而不是取消请求本身。在调用MPI_CANCEL和后绪的MPI_WAIT或MPI_TEST之后,该请求成为不活动状态,可以被重新激活,完成新的通信。
成功地取消一个缓冲的发送将释放这个即将到来消息占用的缓冲区空间。 取消和通信只能有一个成功。如果一个发送被标记为取消,则它只能是这样两种情况:一种情况是发送正常完成,目标进程收到了发送的消息;一种情况是发送被成功取消,目标进程没有收到任何消息。这时任何匹配的接收必须由另一个发送来满足。如果一个接收被标记为取消,则它也必须处于成功接收或者成功取消两种情况之一(后一种情况中接收缓冲没有被改变)。这时任何匹配的发送必须由另一个接收来满足。
如果操作被取消,有关信息将在完成该通信的操作的状态(status)参数中返回。
MPI_TEST_CANCELLED(status,flag)
IN status 状态目标(status)
OUT flag (logical)
int MPI_Test_cancelled(MPI_Status status, int *flag)
MPI_TEST_CANCELLED(STATUS,FLAG,IERROR)
LOGICAL FLAG
INTEGER STATUS(MPI_STATUS_SIZE),IERROR
当与该状态目标相关的通信被成功取消时返回falg=true。在这种情况下status的所有域(如count或tag)都未定义。否则返回flag=false。如果一个接收参数可能被取消,则用户在检查返回状态的其它域之前应该首先调用MPI_TEST_CANCELLED来检查操作是否被取消。
##对用户的建议##
取消操作可能是一个"昂贵"操作,只有在一些例外情况下才应该使用。
##对操作员的建议##
如果一个发送使用“紧急”协议(数据在发出匹配接收之前就发送给接收者),则取消该发送可能需要和原来的接收者通信以释放分配的缓冲区。在有些系统上这可能需要中断原来的接收者。注意,当通信可能需要执行MPI_CANCEL时,它仍然是一个本地操作,因为它的完成不依赖于其它进程执行的代码。如果一个处理过程需要其它进程,则它应该对应用透明(因此需要一个中断和一个中断句柄)
Copyright: NPACT |