3.7.3 通信完成 BACKWARDFORWARD


函数MPI_WAIT和MPI_TEST用于完成一个非阻塞通信。一个操作的完成表示现在这个发送者可自由地修改在发送缓存(这个发送操作本身离开不改变的发送缓存的内容)中的数据。它不表示消息已被接收,而它可以被通讯子系统缓存。但是,如果使用一个同步模式的发送,那么发送操作的完成表示一个匹配接收被初始化了,并且这个匹配的接收最终将接收这个消息。   

一个接收操作的完成表示这个接收缓存包含被接收的消息,接收者可以自由存取它,并设置状态对象。它不表示这个匹配发送操作已被完成(但当然表示这个发送已被初始化)。   

我们将使用下面术语。一个null句柄是有值MPI_REQUEST_NULL的一个句柄。如果请求没有和任何正出发的通信(看3.9节)联结,那么对它的一个持续的请求和这个句柄是不活动的(inactive)。如果一个句柄既不是null也不是不活动的, 那么它是活动的。

MPI_WAIT(request, status)
 INOUT request 请求(句柄)
 OUT status 状态对象(状态类型)

int MPI_Wait(MPI_Request *request, MPI_Status *status)

MPI_WAIT(REQUEST, STATUS, IERROR)
 INTEGER REQUEST, STATUS(MPI_STATUS_SIZE), IERROR

当由request识别的操作完成时, 对MPI_WAIT调用返回。如果和这个请求联结的通信对象已由一个非阻塞发送或接收调用创建,那么这个对象由对MPI_WAIT的调用解出分配并设置请求句柄为MPI_REQUEST_NULL。MPI_WAIT是一个非局部的操作。  

调用在status中返回关于已完成操作的信息。一个接收操作的状态对象的内容能被以3.2.5节描述的方法存取。一个发送操作的状态对象可以被一个对MPI_TEST_CANCELLED(看3.8节)的调用来查寻。   

允许用一个null或不活动的request参数调用MPI_WAIT。这种请况下,这个操作立刻返回。状态参数设为返回tag = MPI_ANY_TAG, source = MPI_ANY_SOURCE,也内部地被构成, 以便对MPI_GET_COUNT和MPI_GET_ELEMENTS的调用返回count=0。   

MPI_TEST(request, flag, status)
 INOUT request 通信请求(句柄)
 OUT flag 如果操作完成则为真(逻辑型)
 OUT status 状态对象(状态类型)

int MPI_Test(MPI_Request,*request, int *flag, MPI_Status *status)

MPI_TEST(REQUEST, FLAG, STATUS, IERROR)
 LOGICAL FLAG
 INTEGER REQUEST, STATUS(MPI_STATUS_SIZE), IERROR

如果由request识别的操作被完成, 那么对MPI_TEST的一个调用返回flag=true(真)。这时,状态变量设为包含关于已完成操作的信息;如果由一个非阻塞发送或接收创建这个通信,那么它被解出分配并设请求句柄为MPI_REQUEST_NULL。否则, 这个调用返回flag = false(假)。这时,状态对象的值无定义。MPI_TEST是一个局部操作。   

一个接收操作的返回状态对象带有能以3.2.5节描述方式存取的信息。一个发送操作的状态对象带有被对MPI_TEST_CANCELLED(看3.8)的调用存取的信息。   

允许用一个null或不活动的request参数调用MPI_TEST。这时操作返回flag =false(假)。   

函数MPI_WAIT和MPI_TEST能被用于完成发送和接收。     

例子3.10 非阻塞操作和MPI_WAIT简单的使用方法。

CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank.EQ.0) THEN
 CALL MPI_ISEND(a(1), 10, MPI_REAL, 1, tag, comm, request, ierr)
 ****给屏蔽延迟作一些计算****
 CALL MPI_WAIT(request, status, ierr)
ELSE
 CALL MPI_IRECV(a(1), 15, MPI_REAL, 0, tag, comm, request, ierr)
 ****给屏蔽延迟作一些计算****
 CALL MPI_WAIT(request, status, ierr)
END IF

如果不为等待所联结通信的完成, 使用下面的操作能解出分配一个请求对象。

MPI_REQUEST_FREE(request)
 INOUT request 通信请求(句柄)

int MPI_Request_free(MPI_Request *request)

MPI_REQUEST_FREE(REQUEST, IERROR)
 INTEGER REQUEST, IERROR

为解出分配标记请求对象, 并设request为MPI_REQUEST_NULL。和这个请求联结一个正出发的通信将被允许完成。只在它完成后,这个请求将被解出分配。   

例如 3.11 使用MPI_REQUEST_FREE的一个例子。

CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank)
IF(rank.EQ.0) THEN
 DO i=1, n
  CALL MPI_ISEND(outval, 1, MPI_real, 1, 0, req, ierr)
  CALL MPI_REQUEST_FREE(req, ierr)
  CALL MPI_IRECV(inval, 1, MPI_REAL, 1, 0, req, ierr)
  CALL MPI_WAIT(req, status, ierr)
 END DO
ELSE ! rank.EQ.1
 CALL MPI_IRECV(inva, 1, MPI_REAL, 0, 0, req, ierr)
 CALL MPI_WAIT(req, status)
 DO I=1, n-1
  CALL MPI_ISEND(outval, 1, MPI_REAL, 0, 0, req, ierr)
  CALL MPI_REQUEST_FREE(req, ierr)
  CALL MPI_IRECV(inval, 1, MPI_REAL, 0, 0, req, ierr)
  CALL MPI_WAIT(req, status, ierr)
 END DO
 CALL MPI_ISEND(outval, 1, MPI_REAL, 0, 0, req, ierr)
 CALL MPI_WAIT(req, status)
END IF


Copyright: NPACT
BACKWARDFORWARD