| |
非阻塞通信的取消
MPI_CANCEL(request)
IN request 非阻塞通信对象(句柄)
int MPI_Cancel(MPI_Request *request)
MPI_CANCEL(REQUEST,IERROR)
INTEGER REQUEST,IERROR
讲解:
MPI_CANCEL操作允许取消已调用的非阻塞通信,用取消命令来释放发送或接收操作所占用的资源,该调用立即返回。取消调用并不意味着相应的通信一定会被取消。若取消操作调用时相应的非阻塞通信已经开始,则它会正常完成,不受取消操作的影响;若取消操作调用时相应的非阻塞通信还没有开始,则可以释放通信占用的资源,取消该非阻塞通信。对于非阻塞通信,即使调用了取消操作,也必须调用非阻塞通信的完成操作或查询对象的释放操作来释放查询对象。
如果一个非阻塞通信已经被执行了取消操作,则该通信的MPI_WAIT或MPI_TEST将释放取消通信的非阻塞通信对象,并且在返回结果status中指明该通信已经被取消。
MPI_TEST_CANCELLED(status,flag)
IN status 状态 (状态类型)
OUT flag 是否取消标志(逻辑类型)
int MPI_Test_cancelled(MPI_Status status, int *flag)
MPI_TEST_CANCELLED(STATUS,FLAG,IERROR)
LOGICAL FLAG
INTEGER STATUS(MPI_STATUS_SIZE),IERROR
讲解:
一个通信操作是否被取消,可以通过调用测试函数MPI_TEST_CANCELLED来检查,如果,MPI_TEST_CANCELLED返回结果flag=true,则表明该通信已经被成功取消,否则说明该通信还没有被取消。
例子
…
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if (rank == 0) {
MPI_Send(sbuf, 1, MPI_INT, 1, 99, MPI_COMM_WORLD );
/* 进程0执行标准数据发送*/
} else if (rank ==1)
{
MPI_Irecv( rbuf, 1, MPI_INT, 0, 99,
MPI_COMM_WORLD, request);
/* 进程1执行非阻塞接收 */
MPI_Cancel( request); /* 然后立即释放该接收操作*/
MPI_Wait(&request,&status);/* 即使该通信被取消,也必须执行完成操作*/
MPI_Test_cancelled(&status,&flag);/*测试取消操作是否成功*/
if (flag) MPI_Irecv( rbuf, 1, MPI_INT, 0, 99
MPI_COMM_WORLD, request);/* 若取消成功,则需要再执行一次接收操作*/
}
非阻塞通信对象的释放
MPI_REQUEST_FREE(request)
INOUT request 非阻塞通信对象
int MPI_Request_free(MPI_Request * request)
MPI_REQUEST_FREE(REQUEST, IERROR)
INTEGER REQUEST, IERROR
讲解:
当程序员能够确认一个非阻塞通信操作完成时,可以直接调用非阻塞通信对象释放语句MPI_REQUEST_FREE将该对象所占用的资源释放,而不是通过调用非阻塞通信完成操作来间接地释放。原来的非阻塞通信对象request变为MPI_REQUEST_NULL。一旦执行了释放操作,非阻塞通信对象就无法再通过其它任何的调用访问。但是,如果与该非阻塞通信对象相联系的通信还没有完成,则该对象的资源并不会立即释放,它将等到该非阻塞通信结束后再释放,因此,非阻塞通信对象的释放并不影响该非阻塞通信的完成。
例子
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)
C 释放掉req,仍能保证MPI_ISEND正常完成
CALL MPI_IRECV(inval, 1, MPI_REAL, 1, 0, req, ierr)
C 重新使用req作为另一个非阻塞通信的句柄
CALL MPI_WAIT(req, status, ierr)
C 正常完成MPI_IRECV
END DO
ELSE IF(rank.EQ.1) THEN
CALL MPI_IRECV(inva, 1, MPI_REAL, 0, 0, req, ierr)
CALL MPI_WAIT(req, status)
C 为了通信的安全,先执行一个接收操作,和进程0的发送操作相匹配
DO I=1, n-1
CALL MPI_ISEND(outval, 1, MPI_REAL, 0, 0, req, ierr)
CALL MPI_REQUEST_FREE(req, ierr)
C 释放掉req,仍可以保证MPI_ISEND正常完成
CALL MPI_IRECV(inval, 1, MPI_REAL, 0, 0, req, ierr)
C 利用释放后的句柄req进行新的非阻塞通信
CALL MPI_WAIT(req, status, ierr)
C 正常完成MPI_IRECV
END DO
CALL MPI_ISEND(outval, 1, MPI_REAL, 0, 0, req, ierr)
CALL MPI_WAIT(req, status)
END IF
|
|