ENH: add node-based gatherList()
This commit is contained in:
parent
c4b261c615
commit
a01f3ed8b7
@ -459,6 +459,17 @@ public:
|
|||||||
const int communicator
|
const int communicator
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Gather data, keeping individual values separate.
|
||||||
|
// \returns True if topo algorithm was applied
|
||||||
|
template<class T>
|
||||||
|
static bool gatherList_topo_algorithm
|
||||||
|
(
|
||||||
|
//! [in,out]
|
||||||
|
UList<T>& values,
|
||||||
|
const int tag,
|
||||||
|
const int communicator
|
||||||
|
);
|
||||||
|
|
||||||
//- Implementation: inverse of gatherList_algorithm
|
//- Implementation: inverse of gatherList_algorithm
|
||||||
template<class T>
|
template<class T>
|
||||||
static void scatterList_algorithm
|
static void scatterList_algorithm
|
||||||
|
@ -252,6 +252,127 @@ void Foam::Pstream::gatherList_algorithm
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool Foam::Pstream::gatherList_topo_algorithm
|
||||||
|
(
|
||||||
|
UList<T>& values,
|
||||||
|
const int tag,
|
||||||
|
const int communicator
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const bool withTopo =
|
||||||
|
(
|
||||||
|
UPstream::is_parallel(communicator)
|
||||||
|
&& UPstream::usingTopoControl(UPstream::topoControls::gatherList)
|
||||||
|
&& UPstream::usingNodeComms(communicator)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (withTopo)
|
||||||
|
{
|
||||||
|
// Topological gathering
|
||||||
|
|
||||||
|
if (FOAM_UNLIKELY(values.size() < UPstream::nProcs(communicator)))
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "List of values:" << values.size()
|
||||||
|
<< " < numProcs:" << UPstream::nProcs(communicator) << nl
|
||||||
|
<< Foam::abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overall node-wise offsets
|
||||||
|
const auto& off = UPstream::interNode_offsets();
|
||||||
|
|
||||||
|
// The per-node processor range
|
||||||
|
const auto& nodeProcs = UPstream::localNode_parentProcs();
|
||||||
|
|
||||||
|
// The per-node sub-section of values
|
||||||
|
auto nodeValues = values.slice(nodeProcs.start(), nodeProcs.size());
|
||||||
|
|
||||||
|
// Stage 1: gather values within a node
|
||||||
|
// - linear for local-node (assume communication is fast)
|
||||||
|
|
||||||
|
if (UPstream::is_parallel(UPstream::commLocalNode()))
|
||||||
|
{
|
||||||
|
const auto subComm = UPstream::commLocalNode();
|
||||||
|
constexpr bool linear(true);
|
||||||
|
|
||||||
|
Pstream::gatherList_algorithm<T>
|
||||||
|
(
|
||||||
|
UPstream::whichCommunication(subComm, linear),
|
||||||
|
nodeValues,
|
||||||
|
tag,
|
||||||
|
subComm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stage 2: gather between node leaders
|
||||||
|
// - this unfortunately corresponds to a gatherv process
|
||||||
|
// (number of cores per node is not identical)
|
||||||
|
// - code strongly resembles globalIndex::gather
|
||||||
|
|
||||||
|
if (UPstream::is_parallel(UPstream::commInterNode()))
|
||||||
|
{
|
||||||
|
const auto subComm = UPstream::commInterNode();
|
||||||
|
|
||||||
|
if (UPstream::master(subComm))
|
||||||
|
{
|
||||||
|
for (const int proci : UPstream::subProcs(subComm))
|
||||||
|
{
|
||||||
|
auto slot =
|
||||||
|
values.slice(off[proci], off[proci+1]-off[proci]);
|
||||||
|
|
||||||
|
// Probably not contiguous though,
|
||||||
|
// otherwise would have used mpiGather()
|
||||||
|
|
||||||
|
if constexpr (is_contiguous_v<T>)
|
||||||
|
{
|
||||||
|
UIPstream::read
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::scheduled,
|
||||||
|
proci,
|
||||||
|
slot,
|
||||||
|
tag,
|
||||||
|
subComm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IPstream::recv(slot, proci, tag, subComm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if constexpr (is_contiguous_v<T>)
|
||||||
|
{
|
||||||
|
UOPstream::write
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::scheduled,
|
||||||
|
UPstream::masterNo(),
|
||||||
|
nodeValues,
|
||||||
|
tag,
|
||||||
|
subComm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OPstream::send
|
||||||
|
(
|
||||||
|
nodeValues,
|
||||||
|
UPstream::commsTypes::scheduled,
|
||||||
|
UPstream::masterNo(),
|
||||||
|
tag,
|
||||||
|
subComm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return withTopo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void Foam::Pstream::scatterList_algorithm
|
void Foam::Pstream::scatterList_algorithm
|
||||||
(
|
(
|
||||||
@ -448,7 +569,15 @@ void Foam::Pstream::gatherList
|
|||||||
auto* ptr = values.data() + UPstream::myProcNo(communicator);
|
auto* ptr = values.data() + UPstream::myProcNo(communicator);
|
||||||
UPstream::mpiGather(ptr, ptr, 1, communicator);
|
UPstream::mpiGather(ptr, ptr, 1, communicator);
|
||||||
}
|
}
|
||||||
else
|
else if
|
||||||
|
(
|
||||||
|
!Pstream::gatherList_topo_algorithm
|
||||||
|
(
|
||||||
|
values,
|
||||||
|
tag,
|
||||||
|
communicator
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Communication order
|
// Communication order
|
||||||
const auto& commOrder = UPstream::whichCommunication(communicator);
|
const auto& commOrder = UPstream::whichCommunication(communicator);
|
||||||
@ -486,6 +615,15 @@ void Foam::Pstream::allGatherList
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// IMPORTANT: always call the *_algorithm() versions here and
|
||||||
|
// never the base versions [eg, Pstream::gatherList()] since
|
||||||
|
// the communcation order must be absolutely identical
|
||||||
|
// for the gatherList and scatterList, otherwise the results will
|
||||||
|
// not replicate the allGather behaviour.
|
||||||
|
//
|
||||||
|
// This also means that we must avoid the gatherList_topo_algorithm()
|
||||||
|
// as well, since this does not pair well with scatterList_algorithm()
|
||||||
|
|
||||||
// Communication order
|
// Communication order
|
||||||
const auto& commOrder = UPstream::whichCommunication(communicator);
|
const auto& commOrder = UPstream::whichCommunication(communicator);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user