ENH: added UPstream::waitAnyRequest(UList<UPstream::Request>&)

- waits for completion of any of the listed requests and returns the
  corresponding index into the list.
  This allows, for example, dispatching of data when the receive is
  completed.
This commit is contained in:
Mark Olesen
2023-02-09 10:58:59 +01:00
parent add61ca273
commit 422654a9ea
9 changed files with 550 additions and 0 deletions

View File

@ -506,6 +506,11 @@ public:
// A no-op if parRun() == false or the list is empty
static void waitRequests(UList<UPstream::Request>& requests);
//- Wait until any request has finished and return its index.
// Returns -1 if parRun() == false, or the list is empty,
// or if all the requests have already been handled
static label waitAnyRequest(UList<UPstream::Request>& requests);
//- Wait until request i has finished.
// A no-op if parRun() == false,
// there are no pending requests,

View File

@ -56,6 +56,11 @@ void Foam::UPstream::resetRequests(const label n) {}
void Foam::UPstream::waitRequests(const label pos) {}
void Foam::UPstream::waitRequests(UList<UPstream::Request>&) {}
Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>&)
{
return -1;
}
void Foam::UPstream::waitRequest(const label i) {}
void Foam::UPstream::waitRequest(UPstream::Request&) {}

View File

@ -170,6 +170,57 @@ void Foam::UPstream::waitRequests(UList<UPstream::Request>& requests)
}
Foam::label Foam::UPstream::waitAnyRequest(UList<UPstream::Request>& requests)
{
// No-op for non-parallel or no pending requests
if (!UPstream::parRun() || requests.empty())
{
return -1;
}
// Looks ugly but is legitimate since UPstream::Request is an intptr_t,
// which is always large enough to hold an MPI_Request (int or pointer)
label count = 0;
auto* waitRequests = reinterpret_cast<MPI_Request*>(requests.data());
// Transcribe UPstream::Request into MPI_Request
// - do not change locations within the list since these are relevant
// for the return index.
for (auto& req : requests)
{
waitRequests[count] = PstreamDetail::Request::get(req);
++count;
}
profilingPstream::beginTiming();
// On success: sets request to MPI_REQUEST_NULL
int index = -1;
if (MPI_Waitany(count, waitRequests, &index, MPI_STATUS_IGNORE))
{
FatalErrorInFunction
<< "MPI_Waitany returned with error"
<< Foam::abort(FatalError);
}
profilingPstream::addWaitTime();
if (index == MPI_UNDEFINED)
{
index = -1; // No outstanding requests
}
// Transcribe MPI_Request back into UPstream::Request
while (--count >= 0)
{
requests[count] = UPstream::Request(waitRequests[count]);
}
return index;
}
// FUTURE?
//
/// void Foam::UPstream::waitRequests