ENH: provide UPstream::finishedRequests() support

- for querying all outstanding requests:

     if (UPstream::finishedRequests(startRequest)) ...
     if (UPstream::finishedRequests(startRequest, -1)) ...

- for querying slice of outstanding requests:

     if (UPstream::finishedRequests(startRequest, 10)) ...
This commit is contained in:
Mark Olesen
2023-04-14 15:00:03 +02:00
parent 80bc1db5b7
commit 66a7f0c9db
3 changed files with 152 additions and 59 deletions

View File

@ -559,8 +559,13 @@ public:
// if the position is out-of-range [0 to nRequests()],
// or the internal list of requests is empty.
//
// If checking a trailing portion of the list, it will also trim
// the list of outstanding requests as a side-effect.
// This is a feature (not a bug) to conveniently manange the list.
//
// \param pos starting position within the internal list of requests
static void waitRequests(const label pos);
// \param len length of slice to check (negative = until the end)
static void waitRequests(const label pos, label len = -1);
//- Wait until all requests have finished.
//- Corresponds to MPI_Waitall()
@ -577,7 +582,8 @@ public:
// \returns false if all requests have already been handled.
//
// \param pos starting position within the internal list of requests
static bool waitAnyRequest(const label pos);
// \param len length of slice to check (negative = until the end)
static bool waitAnyRequest(const label pos, label len = -1);
//- Wait until some requests (from position onwards) have finished.
//- Corresponds to MPI_Waitsome()
@ -630,6 +636,18 @@ public:
// or for a null-request
static bool finishedRequest(UPstream::Request& req);
//- Non-blocking comms: have all requests (from position onwards)
//- finished?
//- Corresponds to MPI_Testall()
// A no-op and returns true if parRun() == false,
// if there are no pending requests,
// or if the index is out-of-range (0 to nRequests)
// or the addressed range is empty etc.
//
// \param pos starting position within the internal list of requests
// \param len length of slice to check (negative = until the end)
static bool finishedRequests(const label pos, label len = -1);
//- Non-blocking comms: have all requests finished?
//- Corresponds to MPI_Testall()
// A no-op and returns true if parRun() == false or list is empty

View File

@ -53,10 +53,10 @@ Foam::label Foam::UPstream::nRequests() noexcept { return 0; }
void Foam::UPstream::resetRequests(const label n) {}
void Foam::UPstream::waitRequests(const label pos) {}
void Foam::UPstream::waitRequests(const label pos, label len) {}
void Foam::UPstream::waitRequests(UList<UPstream::Request>&) {}
bool Foam::UPstream::waitAnyRequest(const label pos)
bool Foam::UPstream::waitAnyRequest(const label pos, label len)
{
return false;
}
@ -82,6 +82,12 @@ void Foam::UPstream::waitRequest(UPstream::Request&) {}
bool Foam::UPstream::finishedRequest(const label i) { return true; }
bool Foam::UPstream::finishedRequest(UPstream::Request&) { return true; }
bool Foam::UPstream::finishedRequests(const label pos, label len)
{
return true;
}
bool Foam::UPstream::finishedRequests(UList<UPstream::Request>&)
{
return true;

View File

@ -69,28 +69,31 @@ void Foam::UPstream::resetRequests(const label n)
}
void Foam::UPstream::waitRequests(const label pos)
void Foam::UPstream::waitRequests(const label pos, label len)
{
// No-op for non-parallel, no pending requests or out-of-range
if
(
!UPstream::parRun()
|| pos < 0
|| pos >= PstreamGlobals::outstandingRequests_.size()
/// || !len
|| (pos < 0 || pos >= PstreamGlobals::outstandingRequests_.size())
|| !len
)
{
return;
}
label count = (PstreamGlobals::outstandingRequests_.size() - pos);
bool trim = true; // Trim the trailing part of the list
/// // Treat len < 0 like npos (ie, the rest of the list) but also
/// // apply range checking to avoid bad slices
/// if (len > 0 && len < count)
/// {
/// count = len;
/// }
// Apply range-checking on slice with (len < 0) behaving like npos
// (ie, the rest of the list)
if (len >= 0 && len < count)
{
// A non-trailing slice
count = len;
trim = false;
}
// Have count >= 1
auto* waitRequests = (PstreamGlobals::outstandingRequests_.data() + pos);
@ -102,18 +105,34 @@ void Foam::UPstream::waitRequests(const label pos)
profilingPstream::beginTiming();
// On success: sets each request to MPI_REQUEST_NULL
if (MPI_Waitall(count, waitRequests, MPI_STATUSES_IGNORE))
if (count == 1)
{
FatalErrorInFunction
<< "MPI_Waitall returned with error"
<< Foam::abort(FatalError);
// On success: sets request to MPI_REQUEST_NULL
if (MPI_Wait(waitRequests, MPI_STATUS_IGNORE))
{
FatalErrorInFunction
<< "MPI_Wait returned with error"
<< Foam::abort(FatalError);
}
}
else if (count > 1)
{
// On success: sets each request to MPI_REQUEST_NULL
if (MPI_Waitall(count, waitRequests, MPI_STATUSES_IGNORE))
{
FatalErrorInFunction
<< "MPI_Waitall returned with error"
<< Foam::abort(FatalError);
}
}
profilingPstream::addWaitTime();
// ie, resetRequests(pos)
PstreamGlobals::outstandingRequests_.resize(pos);
if (trim)
{
PstreamGlobals::outstandingRequests_.resize(pos);
}
if (UPstream::debug)
{
@ -170,15 +189,14 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests)
}
bool Foam::UPstream::waitAnyRequest(const label pos)
bool Foam::UPstream::waitAnyRequest(const label pos, label len)
{
// No-op for non-parallel, no pending requests or out-of-range
if
(
!UPstream::parRun()
|| pos < 0
|| pos >= PstreamGlobals::outstandingRequests_.size()
/// || !len
|| (pos < 0 || pos >= PstreamGlobals::outstandingRequests_.size())
|| !len
)
{
return false;
@ -186,13 +204,14 @@ bool Foam::UPstream::waitAnyRequest(const label pos)
label count = (PstreamGlobals::outstandingRequests_.size() - pos);
/// // Treat len < 0 like npos (ie, the rest of the list) but also
/// // apply range checking to avoid bad slices
///
/// if (len >= 0 && len < count)
/// {
/// count = len;
/// }
// Apply range-checking on slice with (len < 0) behaving like npos
// (ie, the rest of the list)
if (len >= 0 && len < count)
{
// A non-trailing slice
count = len;
}
// Have count >= 1
auto* waitRequests = (PstreamGlobals::outstandingRequests_.data() + pos);
@ -235,9 +254,8 @@ bool Foam::UPstream::waitSomeRequests
if
(
!UPstream::parRun()
|| pos < 0
|| pos >= PstreamGlobals::outstandingRequests_.size()
/// || !len
|| (pos < 0 || pos >= PstreamGlobals::outstandingRequests_.size())
// || !len
)
{
if (indices)
@ -249,13 +267,14 @@ bool Foam::UPstream::waitSomeRequests
label count = (PstreamGlobals::outstandingRequests_.size() - pos);
/// // Treat len < 0 like npos (ie, the rest of the list) but also
/// // apply range checking to avoid bad slices
///
/// if (len >= 0 && len < count)
/// {
/// count = len;
/// }
// Apply range-checking on slice with (len < 0) behaving like npos
// (ie, the rest of the list)
// if (len >= 0 && len < count)
// {
// // A non-trailing slice
// count = len;
// }
// Have count >= 1
auto* waitRequests = (PstreamGlobals::outstandingRequests_.data() + pos);
@ -524,6 +543,12 @@ bool Foam::UPstream::finishedRequest(const label i)
return true;
}
if (UPstream::debug)
{
Pout<< "UPstream::finishedRequest : check request:"
<< i << endl;
}
auto& request = PstreamGlobals::outstandingRequests_[i];
// Fast-path (no-op) for null request
@ -532,22 +557,10 @@ bool Foam::UPstream::finishedRequest(const label i)
return true;
}
if (UPstream::debug)
{
Pout<< "UPstream::finishedRequest : checking request:"
<< i << endl;
}
// On success: sets request to MPI_REQUEST_NULL
int flag = 0;
MPI_Test(&request, &flag, MPI_STATUS_IGNORE);
if (UPstream::debug)
{
Pout<< "UPstream::finishedRequest : finished request:" << i
<< endl;
}
return flag != 0;
}
@ -581,6 +594,62 @@ bool Foam::UPstream::finishedRequest(UPstream::Request& req)
}
bool Foam::UPstream::finishedRequests(const label pos, label len)
{
// No-op for non-parallel, or out-of-range (eg, placeholder indices)
if
(
!UPstream::parRun()
|| (pos < 0 || pos >= PstreamGlobals::outstandingRequests_.size())
|| !len
)
{
return true;
}
label count = (PstreamGlobals::outstandingRequests_.size() - pos);
// Apply range-checking on slice with (len < 0) behaving like npos
// (ie, the rest of the list)
if (len >= 0 && len < count)
{
// A non-trailing slice
count = len;
}
// Have count >= 1
if (UPstream::debug)
{
Pout<< "UPstream::finishedRequests : check " << count
<< " requests starting at " << pos << endl;
}
auto* waitRequests = (PstreamGlobals::outstandingRequests_.data() + pos);
int flag = 1;
if (count == 1)
{
// Fast-path (no-op) for single null request
if (MPI_REQUEST_NULL == *waitRequests)
{
return true;
}
// On success: sets request to MPI_REQUEST_NULL
MPI_Test(waitRequests, &flag, MPI_STATUS_IGNORE);
}
else if (count > 1)
{
// On success: sets each request to MPI_REQUEST_NULL
// On failure: no request is modified
MPI_Testall(count, waitRequests, &flag, MPI_STATUSES_IGNORE);
}
return flag != 0;
}
bool Foam::UPstream::finishedRequests(UList<UPstream::Request>& requests)
{
// No-op for non-parallel or no pending requests
@ -721,12 +790,12 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
if (req1 >= 0)
{
PstreamGlobals:: outstandingRequests_[req1] = waitRequests[0];
PstreamGlobals::outstandingRequests_[req1] = waitRequests[0];
}
if (req2 >= 0)
{
PstreamGlobals:: outstandingRequests_[req2] = waitRequests[1];
PstreamGlobals::outstandingRequests_[req2] = waitRequests[1];
}
// Flag indices as 'done'
@ -744,7 +813,7 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
{
if (req1 >= 0)
{
PstreamGlobals:: outstandingRequests_[req1] = waitRequests[0];
PstreamGlobals::outstandingRequests_[req1] = waitRequests[0];
req1 = -1;
}
}
@ -752,7 +821,7 @@ bool Foam::UPstream::finishedRequestPair(label& req1, label& req2)
{
if (req2 >= 0)
{
PstreamGlobals:: outstandingRequests_[req2] = waitRequests[1];
PstreamGlobals::outstandingRequests_[req2] = waitRequests[1];
req2 = -1;
}
}
@ -775,7 +844,7 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2)
int count = 0;
MPI_Request waitRequests[2];
// No-op for non-parallel, or out-of-range (eg, placeholder indices)
// No-op for out-of-range (eg, placeholder indices)
if (req1 >= 0 && req1 < PstreamGlobals::outstandingRequests_.size())
{
waitRequests[0] = PstreamGlobals::outstandingRequests_[req1];
@ -787,7 +856,7 @@ void Foam::UPstream::waitRequestPair(label& req1, label& req2)
req1 = -1; // Flag as 'done'
}
// No-op for non-parallel, or out-of-range (eg, placeholder indices)
// No-op for out-of-range (eg, placeholder indices)
if (req2 >= 0 && req2 < PstreamGlobals::outstandingRequests_.size())
{
waitRequests[1] = PstreamGlobals::outstandingRequests_[req2];