Skip to content

Commit 4679ebf

Browse files
committed
MPI_Waitsome performance improvement
by avoiding extra atomic exchanges. The fix is based on MPI spec: 12.4.2 Multiple threads completing the same request. A program in which two threads block, waiting on the same request, is erroneous. Similarly, the same request cannot appear in the array of requests of two concurrent MPI_{WAIT|TEST}{ANY|SOME|ALL} calls. In MPI, a request can only be completed once. Any combination of wait or test that violates this rule is erroneous." We add marked flag to the request structure. Only MPI_Waitsome thread will use/access it by any means. PML threads will not see/touch it. So given that any particular request can be used no more than in one MPI_Waitsome we are safe to do this change.
1 parent 8ef1e26 commit 4679ebf

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

ompi/request/req_wait.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,8 @@ int ompi_request_default_wait_some(size_t count,
394394
num_requests_null_inactive++;
395395
continue;
396396
}
397-
398-
if( !OPAL_ATOMIC_CMPSET_PTR(&request->req_complete, REQUEST_PENDING, &sync) ) {
397+
indices[i] = OPAL_ATOMIC_CMPSET_PTR(&request->req_complete, REQUEST_PENDING, &sync);
398+
if( !indices[i] ) {
399399
/* If the request is completed go ahead and mark it as such */
400400
assert( REQUEST_COMPLETE(request) );
401401
num_requests_done++;
@@ -426,15 +426,23 @@ int ompi_request_default_wait_some(size_t count,
426426
if( request->req_state == OMPI_REQUEST_INACTIVE ) {
427427
continue;
428428
}
429-
/* Atomically mark the request as pending. If this succeed
430-
* then the request was not completed, and it is now marked as
431-
* pending. Otherwise, the request is complete )either it was
432-
* before or it has been meanwhile). The major drawback here
433-
* is that we will do all the atomics operations in all cases.
429+
/* Here we have 3 possibilities:
430+
* a) request was found completed in the first loop
431+
* => ( indices[i] == 0 )
432+
* b) request was completed between first loop and this check
433+
* => ( indices[i] == 1 ) and we can NOT atomically mark the
434+
* request as pending.
435+
* c) request wasn't finished yet
436+
* => ( indices[i] == 1 ) and we CAN atomically mark the
437+
* request as pending.
438+
* NOTE that in any case (i >= num_requests_done) as latter grows
439+
* either slowly (in case of partial completion)
440+
* OR in parallel with `i` (in case of full set completion)
434441
*/
435-
if( !OPAL_ATOMIC_CMPSET_PTR(&request->req_complete, &sync, REQUEST_PENDING) ) {
436-
indices[num_requests_done] = i;
437-
num_requests_done++;
442+
if( !indices[i] ){
443+
indices[num_requests_done++] = i;
444+
} else if( !OPAL_ATOMIC_CMPSET_PTR(&request->req_complete, &sync, REQUEST_PENDING) ) {
445+
indices[num_requests_done++] = i;
438446
}
439447
}
440448
sync_unsets = count - num_requests_null_inactive - num_requests_done;

0 commit comments

Comments
 (0)