3.7.5 多路完成 BACKWARDFORWARD


能等待一个表中的任何、一些或全部操作的完成是方便的, 而不必等待一个特别消息。对MPI_WAITANY或MPI_TESTANY的一个调用能被用于等待几个操作之一的完成。对MPI_WAITALL或MPI_TESTALL的一个调用能被用于等待一个表中的所有挂起操作。对MPI_WAITSOME或MPI_TESTSOME的一个调用能被用于完成一个表中的所有操作。

MPI_WAITANY(count, array_of_requests, index, status)
 IN count 表长(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT index 被完成操作的句柄索引(整型)
 OUT status 状态对象(状态类型)

int MPI_Waitany(int count, MPI_Request *array_of_requests, int *index,
 MPI_Status *status)

MPI_WAITANY(COUNT, ARRAY_OF_REQUESTS, INDEX, STATUS, IERROR)
 INTEGER COUNT, ARRAY_OF_REQUESTS(*), INDEX, STATUS(MPI_STATUS_SIZE),  
 IERROR

阻止直到与数组联结的操作之一已被完成。如果多于一个操作能终结,那么这个是被任意选择的。在index中返回这个数组的那个请求的索引, 在status中返回正完成通信的状态。(C语言中, 数组下标从0开始, Fortran中下标从1开始)如果一个非阻塞通信操作已分配这个请求,那么解出分配并设置请求句柄为MPI_REQUEST_NULL。   

这个array_of_requests表可以包含null或不活动句柄。如果这个表包含非活动句柄(表长0或所有输入是null或非活动),那么这个调用用index=MPI_UNDEFINED。MPI_WAITANY(count, array_of_requests, index, status)的执行与MPI_WAIT(&array_of_requests[i],status)的执行有相同的作用, 这个i是index的返回值。有包含活输入的一个数组的MPI_WAITANY等价于MPI_WAIT。

MPI_TESTANY(count, array_of_requests, index, flag, status)
 IN count 表长(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT index 被完成操作的索引, 或MPI_UNDEFINED如果没有被 完成的(整型)
 OUT flag 真, 如果一个操作完成(逻辑型)
 OUT status 状态对象(状态类型)

int MPI_Testany(int count, MPI_Request *array_of_requests, int *index,
       int *flag, MPI_Status *status)


MPI_TESTANY(COUNT, ARRAY_OF_REQUESTS, INDEX, FLAG, STATUS, IERROR)
 LOGICAL FLAG
 INTEGER COUNT, ARRAY_OF_REQUESTS(*), INDEX, STATUS(MPI_STATUS_SIZE),  
 IERROR

检测与激活句柄联结的一个或没有操作的完成。前一种情况,它返回flag = 真, 在index中返回这个数组中这个请求的下标, 并在status中返回那个操作的状态; 如果一个非阻塞通信调用分配这个请求, 那么解出这个请求并设句柄为MPI_REQUEST_NULL。(在C语言中, 数组下标从0开始, Fortran中从1开始)在后一种情况, 它返回flag = 假, 在index中返回一个值MPI_UNDEFINED和status为无定义。这个数组可以包含null或不活动句柄。如果数组不包含活动句柄,那么这个调用立刻返回,flag = 假, index = MPI_UNDEFINED, 和status无定义。   

MPI_TESTANY(count, array_of_requests, index, status)的执行与MPI_TEST(&array_of_requests[i], flag, status) 的执行有同样的作用, 对i=0,1 ,..., count-1, 以任意顺序, 直到一个调用返回flag= 真, 或全部失败。在前一种情况,index设为i的最后值, 在后一种情况, 它被设为MPI_UNDEFINED。有包含活动输入的一个数组的MPI_TESTANY是等价于MPI_TEST。   

MPI_WAITALL( count, array_of_requests, array_of_statuses)
 IN count 表长(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT array_of_statuses 状态对象的数组(状态数组)

int MPI_Waitall(int count, MPI_Request *array_of_requests,
       MPI_Status *array_of_statuses)

MPI_WAITALL(COUNT, ARRAY_OF_REQUESTS, ARRAY_OF_STATUSES, IERROR)
 INTEGER COUNT, ARRAY_OF_REQUESTS(*)
 INTEGER ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR

阻止到与表中的活动句柄联结的所有通信操作完成为止, 返回所有这些操作的状态(这包括表中没有活句柄的情况)。两个数组有相同的有效输入数。在数组array_of_statuses中的第i个输入设为第i个操作的返回状态。由非阻塞通信操作创建的请求被解出分配,数组中相应的句柄设为MPI_REQUEST_NULL。这个表可以包含null或非活动句柄。这个调用在每个这样输入状态中返回tag = MPI_ANY_TAG,source =MPI_ANY_SOURCE,并且每个状态输入也被构成,以便调用MPI_GET_COUNT和MPI_GET_ELEMENTS, 返回count = 0。   

对于i = 0, ..., count-1,以任意顺序执行MPI_WAITALL(count,array_of_requests,array_of_statuses), 与MPI_WAIT(&array_of_request[i],&array_of_statuses[i])的执行有相同的作用。有一个长度的数组的MPI_WAITALL等价于MPI_WAIT。

MPI_TESTALL(count, array_of_requests, flag, array_of_statuses)
 IN count 表长(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT flag (逻辑型)
 OUT array_of_statuses 状态对象数组(状态数组)

int MPI_Testall(int count, MPI_Request *array_of_requests, int *flag,
    MPI_Status *array_of_statuses)

MPI_TESTALL(COUNT, ARRAY_OF_REQUESTS, FLAG, ARRAY_OF_STATUSES, IERROR)
 LOGICAL FLAG
 INTEGER COUNT, ARRAY_OF_REQUESTS(*),
 ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR

如果与在数组中活动句柄联结的所有通信都已完成, 返回flag = 真(这包括表中没有活动句柄的情况)。这时,每个相应于一个活动句柄请求的状态输入设为相应通信的状态;如果由一个非阻塞通信调用已分配一个请求,那么解出分配,并设句柄为MPI_REQUEST_NULL。相应于null和非活动句柄的每个状态输入设为返回tag = MPI_ANY_TAG, source = MPI_ANY_SOURCE, 并被安装以便对MPI_GET_COUNT和MPI_GET_ELEMENTS的调用返回count = 0。

否则,返回flag = false(假), 不修改请求, 状态输入的值无定义。这是一个局部操作。

MPI_WAITSOME(incount,array_of_requests,outcount,array_of_indices, array_of_statuses)
 IN incount 请求数组的长度(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT outcount 已完成请求的数目(整型)
 OUT array_of_indices 已完成操作的下标数组(整型数组)
 OUT array_of_statuses 已完成操作的状态数组(状态数组)

int MPI_Waitsome(intincount,MPI_Request *array_of_request, int *outcount,
       int *array_of_indices, MPI_Status *array_of_statuses)

MPI_WAITSOME(INCOUNT, ARRAY_OF_REQUESTS, OUTCOUNT, ARRAY_OF_INDICES,
       ARRAY_OF_STATUSES, IERROR)
 INTEGER INCOUNT, ARRAY_OF_REQUESTS(*), OUTCOUNT, ARRAY_OF_INDICES(*), 
 ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR

等待直到表中与活句柄联结的至少一个操作已完成。在outcount中返回来自已完成的表array_of-requests的请求数目。在数组array_of_indices的第一个outcount位置返回这些操作的下标(在数组array_of_requests中的下标; C中从0开始下标, Fortran中从1开始下标)。在数组array_of_status的第一个outcount位置返回这些已完成操作的状态。如果已完成的一个请求已被一个非阻塞通信调用分配,那么它被解出分配并设所联结的句柄为MPI_REQUEST_NULL。   

如果表中不包含活动句柄, 那么这个调用立刻以outcount = 0 返回。

MPI_TESTSOME(incount,array_of_requests,outcount,array_of_indices,array_of_statuses)
 IN incount 请求数组的长度(整型)
 INOUT array_of_requests 请求数组(句柄数组)
 OUT outcount 已完成请求的数目(整数)
 OUT array_of_indices 已完成操作的下标数组(整型数组)
 OUT array_of_statuses 已完成操作的状态对象数组(状态数组)

int MPI_Testsome(int incount, MPI_Request *array_of_requests, int *outcount,
       int*array_of_indices, MPI_Status *array_of_statuses)
MPI_TESTSOME(INCOUNT, ARRAY_OF_REQUESTS, OUTCOUNT, ARRAY_OF_INDICES,
       ARRAY_OF_STATUSES, IERROR)
 INTEGER INCOUNT, ARRAY_OF_REQUESTS(*), OUTCOUNT,ARRAY_OF_INDICES(*),  
 ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR

除了它立刻返回,行为象MPI_WAITSOME。如果没有操作被完成,它返回outcount = 0。  

MPI_TESTSOME是一个局部操作, 它立刻返回, 而如果传送给它至少包含一个活句柄的一个表时,MPI_WAITSOME将阻塞直到一个通信完成为止。两个调用完成一个合理的请求:如果在一个请求表中重复出现的一个接收请求传送给MPI_WAITSOME或MPI_TESTSOME, 并且一个匹配操作已被登入, 那么接收将最终成功, 除非发送被另一个接收满足; 发送操作类似。   

例子3.14 客户-服务代码(不服务能发生)。

CALL MPI_COMM_SIZE(comm, size, ierr)
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank > 0) THEN ! 客户代码
 DO WHILE(.TRUE.)
  CALL MPI_ISEND(a, n, MPI_REAL, 0, tag, comm, request, ierr)
  CALL MPI_WAIT(request, status, ierr)
 END DO
ELSE ! rank=0 -- 服务器代码
 DO i=1, size-1
  CALL MPI_IRECV(a(1,i), n, MPI_REAL, 0, tag,
       comm, request_list(i), ierr)
 END DO
 DO WHILE(.TRUE.)
  CALL MPI_WAITANY(size-1, request_list, index, status, ierr)
  CALL DO_SERVICE(a(1,index)) !handle one message
  CALL MPI_IRECV(a(1, index), n, MPI_REAL, 0, tag,
       comm, request_list(index), ierr)
 END DO
END IF

例子3.15 使用MPI_WAITSOME的同样的代码。
CALL MPI_COMM_SIZE(comm, size, ierr)
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank > 0) THEN ! 客户代码
 DO WHILE(.TRUE.)
  CALL MPI_ISEND(a, n, MPI_REAL, 0, tag, comm, request, ierr)
  CALL MPI_WAIT(request, status, ierr)
 END DO
ELSE ! rank=0 -- 服务器代码
 DO i=1, size-1
  CALL MPI_IRECV(a(1,i), n, MPI_REAL, 0, tag,
       comm, request_list(i), ierr)
 END DO
 DO WHILE(.TRUE.)
  CALL MPI_WAITSOME(size, request_list, numdone,
           index_list, status_list, ierr)
  DO i=1, numdone
   CALL DO_SERVICE(a(1, index_list(i)))
   CALL MPI_IRECV(a(1, index_list(i)), n, MPI_REAL, 0, tag, comm, request_list(i), ierr)
  END DO
 END DO
END IF


Copyright: NPACT
BACKWARDFORWARD