diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H index acbd44c17d00377fba110b96677867ef29fd02a2..13d477dcfa025a6705a38a34f8db90d5236d58ce 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H @@ -593,6 +593,33 @@ public: // A no-op for non-parallel. No special treatment for null requests. static void addRequest(UPstream::Request& req); + //- Non-blocking comms: cancel and free outstanding request. + //- Corresponds to MPI_Cancel() + MPI_Request_free() + // A no-op if parRun() == false + // if there are no pending requests, + // or if the index is out-of-range (0 to nRequests) + static void cancelRequest(const label i); + + //- Non-blocking comms: cancel and free outstanding request. + //- Corresponds to MPI_Cancel() + MPI_Request_free() + // A no-op if parRun() == false + static void cancelRequest(UPstream::Request& req); + + //- Non-blocking comms: cancel and free outstanding requests. + //- Corresponds to MPI_Cancel() + MPI_Request_free() + // A no-op if parRun() == false or list is empty + static void cancelRequests(UList<UPstream::Request>& requests); + + //- Non-blocking comms: free outstanding request. + //- Corresponds to MPI_Request_free() + // A no-op if parRun() == false + static void freeRequest(UPstream::Request& req); + + //- Non-blocking comms: free outstanding requests. + //- Corresponds to MPI_Request_free() + // A no-op if parRun() == false or list is empty + static void freeRequests(UList<UPstream::Request>& requests); + //- Wait until all requests (from position onwards) have finished. //- Corresponds to MPI_Waitall() // A no-op if parRun() == false, @@ -699,7 +726,7 @@ public: // if there are no pending requests, // or if the indices are out-of-range (0 to nRequests) // Each finished request parameter is set to -1 (ie, done). - static bool finishedRequestPair(label& req1, label& req2); + static bool finishedRequestPair(label& req0, label& req1); //- Non-blocking comms: wait for both requests to finish. //- Corresponds to pair of MPI_Wait() @@ -707,7 +734,7 @@ public: // if there are no pending requests, // or if the indices are out-of-range (0 to nRequests) // Each finished request parameter is set to -1 (ie, done). - static void waitRequestPair(label& req1, label& req2); + static void waitRequestPair(label& req0, label& req1); // General @@ -1271,11 +1298,17 @@ public: //- Reset to default constructed value (MPI_REQUEST_NULL) void reset() noexcept; - //- Same as calling UPstream::waitRequest() - void wait() { UPstream::waitRequest(*this); } + //- Same as calling UPstream::cancelRequest() + void cancel() { UPstream::cancelRequest(*this); } + + //- Same as calling UPstream::freeRequest() + void free() { UPstream::freeRequest(*this); } //- Same as calling UPstream::finishedRequest() bool finished() { return UPstream::finishedRequest(*this); } + + //- Same as calling UPstream::waitRequest() + void wait() { UPstream::waitRequest(*this); } }; diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C index 0e4b2215352ab2a844766c4ebdac0b93dac9fd08..d5a1ac5e9331edbab2b115d735e06c06f230c5cb 100644 --- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C +++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/interfaceFields/processorGAMGInterfaceField/processorGAMGInterfaceField.C @@ -171,9 +171,8 @@ void Foam::processorGAMGInterfaceField::updateInterfaceMatrix { // Fast path: consume straight from receive buffer - // Require receive data. Update the send request state. - // OR: UPstream::waitRequestPair(recvRequest_, sendRequest_); - + // Require receive data. + // Only update the send request state. UPstream::waitRequest(recvRequest_); recvRequest_ = -1; if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1; } diff --git a/src/Pstream/dummy/UPstreamRequest.C b/src/Pstream/dummy/UPstreamRequest.C index 551e766f37491fa985225dc671f2f478d30d6609..f4962ffd451e7ee6e1ae302ba3001bb488d38b90 100644 --- a/src/Pstream/dummy/UPstreamRequest.C +++ b/src/Pstream/dummy/UPstreamRequest.C @@ -53,7 +53,14 @@ Foam::label Foam::UPstream::nRequests() noexcept { return 0; } void Foam::UPstream::resetRequests(const label n) {} -void Foam::UPstream::addRequest(UPstream::Request& req) {} +void Foam::UPstream::addRequest(UPstream::Request&) {} + +void Foam::UPstream::cancelRequest(const label i) {} +void Foam::UPstream::cancelRequest(UPstream::Request&) {} +void Foam::UPstream::cancelRequests(UList<UPstream::Request>&) {} + +void Foam::UPstream::freeRequest(UPstream::Request&) {} +void Foam::UPstream::freeRequests(UList<UPstream::Request>&) {} void Foam::UPstream::waitRequests(const label pos, label len) {} void Foam::UPstream::waitRequests(UList<UPstream::Request>&) {} @@ -96,18 +103,18 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>&) } -bool Foam::UPstream::finishedRequestPair(label& req1, label& req2) +bool Foam::UPstream::finishedRequestPair(label& req0, label& req1) { + req0 = -1; req1 = -1; - req2 = -1; return true; } -void Foam::UPstream::waitRequestPair(label& req1, label& req2) +void Foam::UPstream::waitRequestPair(label& req0, label& req1) { + req0 = -1; req1 = -1; - req2 = -1; } diff --git a/src/Pstream/mpi/UPstreamRequest.C b/src/Pstream/mpi/UPstreamRequest.C index eb8cfc9251188db9ca0dfc0ffe5d9adc103279b9..4f9467fd225b0a7fc3f63ca7eca8019a617bc582 100644 --- a/src/Pstream/mpi/UPstreamRequest.C +++ b/src/Pstream/mpi/UPstreamRequest.C @@ -88,6 +88,118 @@ void Foam::UPstream::addRequest(UPstream::Request& req) } +void Foam::UPstream::cancelRequest(const label i) +{ + // No-op for non-parallel, or out-of-range (eg, placeholder indices) + if + ( + !UPstream::parRun() + || i < 0 + || i >= PstreamGlobals::outstandingRequests_.size() + ) + { + return; + } + + { + auto& request = PstreamGlobals::outstandingRequests_[i]; + if (MPI_REQUEST_NULL != request) // Active handle is mandatory + { + MPI_Cancel(&request); + MPI_Request_free(&request); //<- Sets to MPI_REQUEST_NULL + } + } +} + + +void Foam::UPstream::cancelRequest(UPstream::Request& req) +{ + // No-op for non-parallel + if (!UPstream::parRun()) + { + return; + } + + { + MPI_Request request = PstreamDetail::Request::get(req); + if (MPI_REQUEST_NULL != request) // Active handle is mandatory + { + MPI_Cancel(&request); + MPI_Request_free(&request); + } + req = UPstream::Request(MPI_REQUEST_NULL); // Now inactive + } +} + + +void Foam::UPstream::cancelRequests(UList<UPstream::Request>& requests) +{ + // No-op for non-parallel + if (!UPstream::parRun()) + { + return; + } + + for (auto& req : requests) + { + MPI_Request request = PstreamDetail::Request::get(req); + if (MPI_REQUEST_NULL != request) // Active handle is mandatory + { + MPI_Cancel(&request); + MPI_Request_free(&request); + } + req = UPstream::Request(MPI_REQUEST_NULL); // Now inactive + } +} + + +void Foam::UPstream::freeRequest(UPstream::Request& req) +{ + // No-op for non-parallel + if (!UPstream::parRun()) + { + return; + } + + { + MPI_Request request = PstreamDetail::Request::get(req); + if (MPI_REQUEST_NULL != request) // Active handle is mandatory + { + // if (cancel) + // { + // MPI_Cancel(&request); + // } + MPI_Request_free(&request); + } + req = UPstream::Request(MPI_REQUEST_NULL); // Now inactive + } +} + + +void Foam::UPstream::freeRequests(UList<UPstream::Request>& requests) +{ + // No-op for non-parallel + if (!UPstream::parRun()) + { + return; + } + + for (auto& req : requests) + { + MPI_Request request = PstreamDetail::Request::get(req); + if (MPI_REQUEST_NULL != request) // Active handle is mandatory + { + // if (cancel) + // { + // MPI_Cancel(&request); + // } + MPI_Request_free(&request); + } + req = UPstream::Request(MPI_REQUEST_NULL); // Now inactive + } +} + + void Foam::UPstream::waitRequests(const label pos, label len) { // No-op for non-parallel, no pending requests or out-of-range @@ -178,7 +290,7 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests) { MPI_Request request = PstreamDetail::Request::get(req); - if (MPI_REQUEST_NULL != request) + if (MPI_REQUEST_NULL != request) // Apply some prefiltering { waitRequests[count] = request; ++count; @@ -187,7 +299,7 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests) if (!count) { - // Early exit: has NULL requests only + // No active request handles return; } @@ -422,8 +534,8 @@ Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>& requests) // /// void Foam::UPstream::waitRequests /// ( -/// UPstream::Request& req1, -/// UPstream::Request& req2 +/// UPstream::Request& req0, +/// UPstream::Request& req1 /// ) /// { /// // No-op for non-parallel @@ -435,22 +547,22 @@ Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>& requests) /// int count = 0; /// MPI_Request waitRequests[2]; /// -/// waitRequests[count] = PstreamDetail::Request::get(req1); +/// waitRequests[count] = PstreamDetail::Request::get(req0); /// if (MPI_REQUEST_NULL != waitRequests[count]) /// { -/// // Flag in advance as being handled -/// req1 = UPstream::Request(MPI_REQUEST_NULL); /// ++count; /// } /// -/// waitRequests[count] = PstreamDetail::Request::get(req2); +/// waitRequests[count] = PstreamDetail::Request::get(req1); /// if (MPI_REQUEST_NULL != waitRequests[count]) /// { -/// // Flag in advance as being handled -/// req2 = UPstream::Request(MPI_REQUEST_NULL); /// ++count; /// } /// +/// // Flag in advance as being handled +/// req0 = UPstream::Request(MPI_REQUEST_NULL); +/// req1 = UPstream::Request(MPI_REQUEST_NULL); +/// /// if (!count) /// { /// return; @@ -544,8 +656,7 @@ void Foam::UPstream::waitRequest(UPstream::Request& req) profilingPstream::addWaitTime(); - // Handled, reset to MPI_REQUEST_NULL - req = UPstream::Request(MPI_REQUEST_NULL); + req = UPstream::Request(MPI_REQUEST_NULL); // Now inactive } @@ -605,7 +716,7 @@ bool Foam::UPstream::finishedRequest(UPstream::Request& req) if (flag) { - // Success: reset request to MPI_REQUEST_NULL + // Success: now inactive req = UPstream::Request(MPI_REQUEST_NULL); } @@ -687,7 +798,7 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests) { MPI_Request request = PstreamDetail::Request::get(req); - if (MPI_REQUEST_NULL != request) + if (MPI_REQUEST_NULL != request) // Apply some prefiltering { waitRequests[count] = request; ++count; @@ -696,7 +807,7 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests) if (!count) { - // Early exit: has NULL requests only + // No active handles return true; } @@ -736,45 +847,60 @@ bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests) } -bool Foam::UPstream::finishedRequestPair(label& req1, label& req2) +bool Foam::UPstream::finishedRequestPair(label& req0, label& req1) { // No-op for non-parallel if (!UPstream::parRun()) { + req0 = -1; req1 = -1; - req2 = -1; return true; } - int count = 0; + bool anyActive = false; MPI_Request waitRequests[2]; - // In range? - if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size()) + // No-op for out-of-range (eg, placeholder indices) + + if (req0 >= 0 && req0 < PstreamGlobals::outstandingRequests_.size()) { - waitRequests[0] = PstreamGlobals::outstandingRequests_[req1]; - ++count; + waitRequests[0] = PstreamGlobals::outstandingRequests_[req0]; } else { waitRequests[0] = MPI_REQUEST_NULL; - req1 = -1; } - // No-op for non-parallel, or out-of-range (eg, placeholder indices) - if (req2 >= 0 && req2 < PstreamGlobals::outstandingRequests_.size()) + if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size()) { - waitRequests[1] = PstreamGlobals::outstandingRequests_[req2]; - ++count; + waitRequests[1] = PstreamGlobals::outstandingRequests_[req1]; } else { waitRequests[1] = MPI_REQUEST_NULL; - req2 = -1; } - if (!count) + if (MPI_REQUEST_NULL != waitRequests[0]) // An active handle + { + anyActive = true; + } + else + { + req0 = -1; + } + + if (MPI_REQUEST_NULL != waitRequests[1]) // An active handle + { + anyActive = true; + } + else { + req1 = -1; + } + + if (!anyActive) + { + // No active handles return true; } @@ -807,41 +933,41 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2) // No active request handles. // Slight pedantic, but copy back requests in case they were altered - if (req1 >= 0) + if (req0 >= 0) { - PstreamGlobals::outstandingRequests_[req1] = waitRequests[0]; + PstreamGlobals::outstandingRequests_[req0] = waitRequests[0]; } - if (req2 >= 0) + if (req1 >= 0) { - PstreamGlobals::outstandingRequests_[req2] = waitRequests[1]; + PstreamGlobals::outstandingRequests_[req1] = waitRequests[1]; } // Flag indices as 'done' + req0 = -1; req1 = -1; - req2 = -1; return true; } // Copy back requests to their 'stack' locations for (int i = 0; i < outcount; ++i) { - int reqid = indices[i]; + const int idx = indices[i]; - if (reqid == 0) + if (idx == 0) { - if (req1 >= 0) + if (req0 >= 0) { - PstreamGlobals::outstandingRequests_[req1] = waitRequests[0]; - req1 = -1; + PstreamGlobals::outstandingRequests_[req0] = waitRequests[0]; + req0 = -1; } } - if (reqid == 1) + if (idx == 1) { - if (req2 >= 0) + if (req1 >= 0) { - PstreamGlobals::outstandingRequests_[req2] = waitRequests[1]; - req2 = -1; + PstreamGlobals::outstandingRequests_[req1] = waitRequests[1]; + req1 = -1; } } } @@ -850,13 +976,13 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2) } -void Foam::UPstream::waitRequestPair(label& req1, label& req2) +void Foam::UPstream::waitRequestPair(label& req0, label& req1) { // No-op for non-parallel. Flag indices as 'done' if (!UPstream::parRun()) { + req0 = -1; req1 = -1; - req2 = -1; return; } @@ -864,32 +990,37 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2) MPI_Request waitRequests[2]; // No-op for out-of-range (eg, placeholder indices) - if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size()) - { - waitRequests[0] = PstreamGlobals::outstandingRequests_[req1]; - ++count; - } - else - { - waitRequests[0] = MPI_REQUEST_NULL; - req1 = -1; // Flag as 'done' - } + // Prefilter inactive handles - // No-op for out-of-range (eg, placeholder indices) - if (req2 >= 0 && req2 < PstreamGlobals::outstandingRequests_.size()) + if (req0 >= 0 && req0 < PstreamGlobals::outstandingRequests_.size()) { - waitRequests[1] = PstreamGlobals::outstandingRequests_[req2]; - ++count; + waitRequests[count] = PstreamGlobals::outstandingRequests_[req0]; + PstreamGlobals::outstandingRequests_[req0] = MPI_REQUEST_NULL; + + if (MPI_REQUEST_NULL != waitRequests[count]) // An active handle + { + ++count; + } } - else + + if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size()) { - waitRequests[1] = MPI_REQUEST_NULL; - req2 = -1; // Flag as 'done' + waitRequests[count] = PstreamGlobals::outstandingRequests_[req1]; + PstreamGlobals::outstandingRequests_[req1] = MPI_REQUEST_NULL; + + if (MPI_REQUEST_NULL != waitRequests[count]) // An active handle + { + ++count; + } } - // Early exit + // Flag in advance as being handled + req0 = -1; + req1 = -1; + if (!count) { + // No active handles return; } @@ -904,23 +1035,6 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2) } profilingPstream::addWaitTime(); - - // Copy back requests to their 'stack' locations - // and flag index as done - - if (req1 >= 0) - { - PstreamGlobals::outstandingRequests_[req1] = waitRequests[0]; - } - - if (req2 >= 0) - { - PstreamGlobals::outstandingRequests_[req2] = waitRequests[1]; - } - - // Flag indices as 'done' - req1 = -1; - req2 = -1; } diff --git a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C index adf9b74a17a539ff422f74c73651b166d05e7d9b..81526549aea059ae870eaf48a6e088de2fe7eb2e 100644 --- a/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C +++ b/src/overset/lduPrimitiveProcessorInterface/GAMG/calculatedProcessorGAMGInterfaceField.C @@ -172,9 +172,8 @@ void Foam::calculatedProcessorGAMGInterfaceField::updateInterfaceMatrix { // Fast path: consume straight from receive buffer - // Require receive data. Update the send request state. - // OR: UPstream::waitRequestPair(recvRequest_, sendRequest_); - + // Require receive data. + // Only update the send request state. UPstream::waitRequest(recvRequest_); recvRequest_ = -1; if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1; }