COMP: native MPI reduce not triggered (fixes #2569)

- define returnReduce *after* defining all specializations for reduce
  so that the compiler does not take the generic templated reduce.

ENH: add UPstream::reduceAnd, UPstream::reduceOr

- direct wrapper of MPI_LAND, MPI_LOR intrinsics

ENH: provide special purpose returnReduce for logical operations

- returnReduceAnd(bool), returnReduceOr(bool) as a inline wrappers
  for returnReduce with andOp<bool>(), orOp<bool>() operators,
  respectively.

  These forms are more succinct and force casting of the parameter
  into a bool. Using MPI bool operations allows vendor/hardware MPI
  optimisations.

  * Test for existence on any rank:

      1.  if (returnReduceOr(list.size()) { ... }
      1b. if (returnReduceOr(!list.empty()) { ... }

      2.  if (returnReduce(bool(list.size(), orOp<bool>())) { ... }
      3.  if (returnReduce(list.size(), sumOp<label>()) != 0) { ... }
      3b. if (returnReduce(list.size(), sumOp<label>()) > 0) { ... }

  * Test for non-existence on all ranks:

      1.  if (returnReduceAnd(list.empty()) { ... }
      1b. if (!returnReduceOr(list.size()) { ... }

      2.  if (returnReduce(list.empty(), andOp<bool>())) { ... }
      3.  if (returnReduce(list.size(), sumOp<label>()) == 0) { ... }

  Notes:
      Form 1. succinct
      Form 2. may require explicit bool() for correct dispatch
      Form 3. more expensive sumOp<label> just for testing size!
      There are also some places using maxOp<label> instead of sumOp<label>
This commit is contained in:
Mark Olesen
2022-08-22 13:12:02 +02:00
parent 968c1db1af
commit 512f558549
7 changed files with 213 additions and 126 deletions

View File

@ -220,7 +220,7 @@ void Foam::Pstream::scatter(T& value, const int tag, const label comm)
#ifndef Foam_Pstream_scatter_nobroadcast
Pstream::broadcast(value, comm);
#else
scatter(UPstream::whichCommunication(comm), value, tag, comm);
Pstream::scatter(UPstream::whichCommunication(comm), value, tag, comm);
#endif
}

View File

@ -80,48 +80,13 @@ void reduce
{
if (UPstream::parRun())
{
reduce(UPstream::whichCommunication(comm), value, bop, tag, comm);
}
}
//- Reduce (copy) and return value
template<class T, class BinaryOp>
T returnReduce
(
const T& value,
const BinaryOp& bop,
const int tag = UPstream::msgType(),
const label comm = UPstream::worldComm
)
{
T work(value);
reduce(work, bop, tag, comm);
return work;
}
//- Reduce inplace (cf. MPI Allreduce)
//- the sum of both value and count (for averaging)
template<class T>
void sumReduce
(
T& value,
label& count,
const int tag = UPstream::msgType(),
const label comm = UPstream::worldComm
)
{
if (UPstream::parRun())
{
reduce(value, sumOp<T>(), tag, comm);
reduce(count, sumOp<label>(), tag, comm);
Foam::reduce(UPstream::whichCommunication(comm), value, bop, tag, comm);
}
}
//- Reduce inplace (cf. MPI Allreduce)
//- multiple values (identical size on all processes!)
//- multiple values (same size on all processes!)
template<class T, class BinaryOp>
void reduce
(
@ -170,9 +135,9 @@ void reduce
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for bool
// Special reductions for bool
//- Logical (and) reduction (cf. MPI AllReduce)
//- Logical (and) inplace reduction. Uses UPstream::reduceAnd
void reduce
(
bool& value,
@ -181,7 +146,7 @@ void reduce
const label comm = UPstream::worldComm
);
//- Logical (or) reduction (cf. MPI AllReduce)
//- Logical (or) inplace reduction. Uses UPstream::reduceOr
void reduce
(
bool& value,
@ -193,7 +158,7 @@ void reduce
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for common reduction types
// Common reductions
#undef Pstream_CommonReductions
#define Pstream_CommonReductions(Native) \
@ -225,7 +190,7 @@ void reduce \
const label comm = UPstream::worldComm \
); \
\
/*! \brief Reduce (sum) multiple Native values (identical size all procs!) */ \
/*! \brief Reduce (sum) multiple Native values (same size all procs!) */ \
void reduce \
( \
Native values[], \
@ -249,31 +214,14 @@ inline void reduce \
}
Pstream_CommonReductions(int32_t);
Pstream_CommonReductions(int64_t);
Pstream_CommonReductions(uint32_t);
Pstream_CommonReductions(uint64_t);
Pstream_CommonReductions(float);
Pstream_CommonReductions(double);
#undef Pstream_CommonReductions
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for floating-point types
// Floating-point reductions
#undef Pstream_FloatReductions
#define Pstream_FloatReductions(Native) \
\
/*! \brief Sum of both Native value and count (for averaging) */ \
void sumReduce \
( \
Native& value, \
label& count, \
const int tag = UPstream::msgType(), /*!< (ignored) */ \
const label comm = UPstream::worldComm \
); \
Pstream_CommonReductions(Native); \
\
/*! \brief Non-blocking reduce (sum) single Native value. Sets request */ \
void reduce \
@ -297,12 +245,115 @@ void reduce \
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Pstream_CommonReductions(int32_t);
Pstream_CommonReductions(int64_t);
Pstream_CommonReductions(uint32_t);
Pstream_CommonReductions(uint64_t);
Pstream_FloatReductions(float);
Pstream_FloatReductions(double);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#undef Pstream_CommonReductions
#undef Pstream_FloatReductions
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Reduce inplace (cf. MPI Allreduce)
//- the sum of both value and count (for averaging)
template<class T>
void sumReduce
(
T& value,
label& count,
const int tag = UPstream::msgType(),
const label comm = UPstream::worldComm
)
{
if (UPstream::parRun())
{
Foam::reduce(value, sumOp<T>(), tag, comm);
Foam::reduce(count, sumOp<label>(), tag, comm);
}
}
// Floating-point sum-reduce
#undef Pstream_SumReduce
#define Pstream_SumReduce(Native) \
\
/*! \brief Sum of both Native value and count (for averaging) */ \
void sumReduce \
( \
Native& value, \
label& count, \
const int tag = UPstream::msgType(), /*!< (ignored) */ \
const label comm = UPstream::worldComm \
);
Pstream_SumReduce(float);
Pstream_SumReduce(double);
#undef Pstream_SumReduce
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Convenience wrappers for some reduction operations
// - defined after all specialisations are known
//- Perform reduction on a copy, using specified binary operation
// \return the resulting value
template<class T, class BinaryOp>
T returnReduce
(
const T& value,
const BinaryOp& bop,
const int tag = UPstream::msgType(),
const label comm = UPstream::worldComm
)
{
T work(value);
Foam::reduce(work, bop, tag, comm);
return work;
}
//- Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd
// \return the resulting value
inline bool returnReduceAnd
(
const bool value,
const label comm = UPstream::worldComm
)
{
bool work(value);
UPstream::reduceAnd(work, comm);
return work;
}
//- Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr
// \return the resulting value
inline bool returnReduceOr
(
const bool value,
const label comm = UPstream::worldComm
)
{
bool work(value);
UPstream::reduceOr(work, comm);
return work;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -712,6 +712,23 @@ public:
);
// Logical reductions
//- Logical (and) reduction (cf. MPI AllReduce)
static void reduceAnd
(
bool& value,
const label communicator = worldComm
);
//- Logical (or) reduction (cf. MPI AllReduce)
static void reduceOr
(
bool& value,
const label communicator = worldComm
);
// Housekeeping
//- Process index of first sub-process

View File

@ -30,7 +30,14 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for bool
// Special reductions for bool
void Foam::UPstream::reduceAnd(bool& value, const label comm)
{}
void Foam::UPstream::reduceOr(bool& value, const label comm)
{}
void Foam::reduce
(
@ -53,7 +60,7 @@ void Foam::reduce
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for common reduction types
// Common reductions
#undef Pstream_CommonReductions
#define Pstream_CommonReductions(Native) \
@ -96,31 +103,14 @@ void Foam::reduce \
{}
Pstream_CommonReductions(int32_t);
Pstream_CommonReductions(int64_t);
Pstream_CommonReductions(uint32_t);
Pstream_CommonReductions(uint64_t);
Pstream_CommonReductions(float);
Pstream_CommonReductions(double);
#undef Pstream_CommonReductions
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for floating-point types
// Floating-point reductions
#undef Pstream_FloatReductions
#define Pstream_FloatReductions(Native) \
\
void Foam::sumReduce \
( \
Native& value, \
label& count, \
const int tag, \
const label comm \
) \
{} \
Pstream_CommonReductions(Native); \
\
void Foam::reduce \
( \
@ -141,12 +131,32 @@ void Foam::reduce \
const label comm, \
label& requestID \
) \
{} \
\
void Foam::sumReduce \
( \
Native& value, \
label& count, \
const int tag, \
const label comm \
) \
{}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Pstream_CommonReductions(int32_t);
Pstream_CommonReductions(int64_t);
Pstream_CommonReductions(uint32_t);
Pstream_CommonReductions(uint64_t);
Pstream_FloatReductions(float);
Pstream_FloatReductions(double);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#undef Pstream_CommonReductions
#undef Pstream_FloatReductions

View File

@ -30,7 +30,6 @@ License
#include <mpi.h>
#include <cinttypes>
#include <cstring> // memmove
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -30,7 +30,6 @@ License
#include <mpi.h>
#include <cinttypes>
#include <cstring> // memmove
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -34,7 +34,19 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for bool
// Special reductions for bool
void Foam::UPstream::reduceAnd(bool& value, const label comm)
{
PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LAND, comm);
}
void Foam::UPstream::reduceOr(bool& value, const label comm)
{
PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LOR, comm);
}
void Foam::reduce
(
@ -44,8 +56,6 @@ void Foam::reduce
const label comm
)
{
// This can also work:
// PstreamDetail::allReduce(&value, 1, MPI_BYTE, MPI_BAND, comm);
PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LAND, comm);
}
@ -58,15 +68,13 @@ void Foam::reduce
const label comm
)
{
// This can also work:
// PstreamDetail::allReduce(&value, 1, MPI_BYTE, MPI_BOR, comm);
PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LOR, comm);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for common reduction types
// Common reductions
#undef Pstream_CommonReductions
#define Pstream_CommonReductions(Native, TaggedType) \
@ -126,49 +134,17 @@ void Foam::reduce \
( \
values, size, TaggedType, MPI_SUM, comm \
); \
} \
Pstream_CommonReductions(int32_t, MPI_INT32_T);
Pstream_CommonReductions(int64_t, MPI_INT64_T);
Pstream_CommonReductions(uint32_t, MPI_UINT32_T);
Pstream_CommonReductions(uint64_t, MPI_UINT64_T);
Pstream_CommonReductions(float, MPI_FLOAT);
Pstream_CommonReductions(double, MPI_DOUBLE);
#undef Pstream_CommonReductions
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specialisations for floating-point types
// Floating-point reductions
#undef Pstream_FloatReductions
#define Pstream_FloatReductions(Native, TaggedType) \
\
void Foam::sumReduce \
( \
Native& value, \
label& count, \
const int tag, /* (unused) */ \
const label comm \
) \
{ \
if (UPstream::parRun()) \
{ \
Native values[2]; \
values[0] = value; \
values[1] = static_cast<Native>(count); \
\
PstreamDetail::allReduce<Native> \
( \
values, 2, TaggedType, MPI_SUM, comm \
); \
\
value = values[0]; \
count = static_cast<label>(values[1]); \
} \
} \
Pstream_CommonReductions(Native, TaggedType); \
\
void Foam::reduce \
( \
@ -199,12 +175,47 @@ void Foam::reduce \
( \
values, size, TaggedType, MPI_SUM, comm, &requestID \
); \
} \
\
void Foam::sumReduce \
( \
Native& value, \
label& count, \
const int tag, /* (unused) */ \
const label comm \
) \
{ \
if (UPstream::parRun() && UPstream::nProcs(comm) > 1) \
{ \
Native values[2]; \
values[0] = static_cast<Native>(count); \
values[1] = value; \
\
PstreamDetail::allReduce<Native> \
( \
values, 2, TaggedType, MPI_SUM, comm \
); \
\
count = static_cast<label>(values[0]); \
value = values[1]; \
} \
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Pstream_CommonReductions(int32_t, MPI_INT32_T);
Pstream_CommonReductions(int64_t, MPI_INT64_T);
Pstream_CommonReductions(uint32_t, MPI_UINT32_T);
Pstream_CommonReductions(uint64_t, MPI_UINT64_T);
Pstream_FloatReductions(float, MPI_FLOAT);
Pstream_FloatReductions(double, MPI_DOUBLE);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#undef Pstream_CommonReductions
#undef Pstream_FloatReductions