ENH: introduce UPstream::commsStructList class

- was previously simply a List<commsStruct>, but now wrap it into a
  class so that the associated communicator index can be easily
  recovered etc.
This commit is contained in:
Mark Olesen
2025-02-11 15:09:36 +01:00
parent 831a55f1ba
commit 3e8b0a2c73
6 changed files with 131 additions and 72 deletions

View File

@ -51,7 +51,7 @@ void printConnection(Ostream& os, const label proci, const labelUList& below)
// The number of receives - as per gatherList (v2112)
void printRecvCount_gatherList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{
@ -91,7 +91,7 @@ void printRecvCount_gatherList
// The number of sends - as per scatterList (v2112)
void printSendCount_scatterList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{
@ -131,7 +131,7 @@ void printSendCount_scatterList
// Transmission widths (contiguous data)
void printWidths
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{

View File

@ -310,7 +310,7 @@ public:
template<class T>
static void gatherList
(
const UList<commsStruct>& comms,
const UPstream::commsStructList& comms,
//! [in,out]
UList<T>& values,
const int tag,
@ -349,7 +349,7 @@ public:
template<class T>
static void scatterList
(
const UList<commsStruct>& comms,
const UPstream::commsStructList& comms,
UList<T>& values,
const int tag,
const label comm

View File

@ -45,7 +45,7 @@ Description
template<class T>
void Foam::Pstream::gatherList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
UList<T>& values,
const int tag,
const label comm
@ -190,7 +190,7 @@ void Foam::Pstream::gatherList
template<class T>
void Foam::Pstream::scatterList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
UList<T>& values,
const int tag,
const label comm

View File

@ -183,8 +183,8 @@ Foam::label Foam::UPstream::getAvailableCommIndex(const label parentIndex)
procIDs_.emplace_back();
// Sizing and filling are demand-driven
linearCommunication_.emplace_back();
treeCommunication_.emplace_back();
linearCommunication_.emplace_back(index);
treeCommunication_.emplace_back(index);
}
return index;
@ -616,26 +616,24 @@ Foam::label Foam::UPstream::procNo
}
const Foam::List<Foam::UPstream::commsStruct>&
const Foam::UPstream::commsStructList&
Foam::UPstream::linearCommunication(const label communicator)
{
if (linearCommunication_[communicator].empty())
{
linearCommunication_[communicator] =
List<commsStruct>(UPstream::nProcs(communicator));
linearCommunication_[communicator].init(communicator);
}
return linearCommunication_[communicator];
}
const Foam::List<Foam::UPstream::commsStruct>&
const Foam::UPstream::commsStructList&
Foam::UPstream::treeCommunication(const label communicator)
{
if (treeCommunication_[communicator].empty())
{
treeCommunication_[communicator] =
List<commsStruct>(UPstream::nProcs(communicator));
treeCommunication_[communicator].init(communicator);
}
return treeCommunication_[communicator];
@ -648,7 +646,7 @@ void Foam::UPstream::printCommTree(const label communicator)
if (UPstream::master(communicator))
{
commsStruct::printGraph(Info(), comms);
comms.printGraph(Info());
}
}
@ -692,10 +690,10 @@ Foam::DynamicList<Foam::List<int>> Foam::UPstream::procIDs_(16);
Foam::DynamicList<Foam::label> Foam::UPstream::parentComm_(16);
Foam::DynamicList<Foam::label> Foam::UPstream::freeComms_;
Foam::DynamicList<Foam::List<Foam::UPstream::commsStruct>>
Foam::DynamicList<Foam::UPstream::commsStructList>
Foam::UPstream::linearCommunication_(16);
Foam::DynamicList<Foam::List<Foam::UPstream::commsStruct>>
Foam::DynamicList<Foam::UPstream::commsStructList>
Foam::UPstream::treeCommunication_(16);

View File

@ -151,19 +151,10 @@ public:
// Member Functions
//- Print un-directed graph in graphviz dot format
static void printGraph
(
Ostream& os,
const UList<UPstream::commsStruct>& comms,
const label proci = 0 // starting node
);
// Access
//- The number of processors addressed by the structure
label nProcs() const;
label nProcs() const noexcept;
//- The procID of the processor \em directly above
label above() const noexcept { return above_; }
@ -188,8 +179,14 @@ public:
//- Reset to default constructed state
void reset();
//- Reset with automatic linear/tree selection
void reset(const label procID, const label numProcs);
//- Reset (automatic linear/tree selection),
//- possibly with communicator-specific adjustments
void reset
(
const label procID,
const label numProcs,
const label comm = -1
);
// Member / Friend Operators
@ -200,6 +197,67 @@ public:
friend Ostream& operator<<(Ostream&, const commsStruct&);
};
//- Collection of communication structures
class commsStructList
{
// Private Data
//- The communicator index
label comm_;
//- The communication tree
List<commsStruct> tree_;
public:
// Constructors
//- Construct empty with invalid communicator
commsStructList() noexcept : comm_(-1) {}
//- Construct empty with given communicator
commsStructList(label comm) noexcept : comm_(comm) {}
// Static Functions
//- An empty structure. Used for placeholders etc.
static const commsStructList& null();
// Member Functions
//- True if communicator is non-negative (ie, was assigned)
bool good() const noexcept { return (comm_ >= 0); }
//- The communicator label
label comm() const noexcept { return comm_; }
//- Clear the list
void clear() { return tree_.clear(); }
//- True if the list is empty
bool empty() const noexcept { return tree_.empty(); }
//- The number of entries
label size() const noexcept { return tree_.size(); }
//- Reset communicator index and clear demand-driven entries
void init(const label comm);
//- Get existing or create (demand-driven) entry
const UPstream::commsStruct& get(const label proci) const;
//- Get existing or create (demand-driven) entry
const UPstream::commsStruct& operator[](const label proci) const
{
return get(proci);
}
//- Print un-directed graph in graphviz dot format
void printGraph(Ostream& os, label proci = 0) const;
};
private:
@ -258,10 +316,10 @@ private:
static DynamicList<label> freeComms_;
//- Linear communication schedule
static DynamicList<List<commsStruct>> linearCommunication_;
static DynamicList<commsStructList> linearCommunication_;
//- Multi level communication schedule
static DynamicList<List<commsStruct>> treeCommunication_;
static DynamicList<commsStructList> treeCommunication_;
// Private Member Functions
@ -1017,15 +1075,13 @@ public:
}
//- Communication schedule for linear all-to-master (proc 0)
static const List<commsStruct>&
linearCommunication
static const commsStructList& linearCommunication
(
const label communicator = worldComm
);
//- Communication schedule for tree all-to-master (proc 0)
static const List<commsStruct>&
treeCommunication
static const commsStructList& treeCommunication
(
const label communicator = worldComm
);
@ -1033,7 +1089,7 @@ public:
//- Communication schedule for all-to-master (proc 0) as
//- linear/tree/none with switching based on UPstream::nProcsSimpleSum
//- and the is_parallel() state
static const List<commsStruct>& whichCommunication
static const commsStructList& whichCommunication
(
const label communicator = worldComm
)
@ -1048,7 +1104,7 @@ public:
return
(
np <= 1
? List<commsStruct>::null()
? commsStructList::null()
: (np <= 2 || np < nProcsSimpleSum)
? linearCommunication(communicator)
: treeCommunication(communicator)
@ -1581,18 +1637,6 @@ public:
Ostream& operator<<(Ostream&, const UPstream::commsStruct&);
// * * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * //
// Template specialisation for access of commsStruct
template<>
UPstream::commsStruct&
UList<UPstream::commsStruct>::operator[](const label procID);
template<>
const UPstream::commsStruct&
UList<UPstream::commsStruct>::operator[](const label procID) const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021-2023 OpenCFD Ltd.
Copyright (C) 2021-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,7 +37,7 @@ namespace Foam
static void printGraph_impl
(
Ostream& os,
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label proci,
label depth,
const label maxDepth = 1024
@ -263,27 +263,26 @@ Foam::UPstream::commsStruct::commsStruct
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::UPstream::commsStruct::printGraph
void Foam::UPstream::commsStructList::printGraph
(
Ostream& os,
const UList<UPstream::commsStruct>& comms,
const label proci
)
) const
{
// Print graph - starting at depth 0
// Avoid corner case when only a single rank involved
// (eg, for node-local communicator)
if (proci < comms.size())
if (proci < size())
{
printGraph_impl(os, comms, proci, 0);
printGraph_impl(os, *this, proci, 0);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::UPstream::commsStruct::nProcs() const
Foam::label Foam::UPstream::commsStruct::nProcs() const noexcept
{
return (1 + allBelow_.size() + allNotBelow_.size());
}
@ -301,7 +300,8 @@ void Foam::UPstream::commsStruct::reset()
void Foam::UPstream::commsStruct::reset
(
const label procID,
const label numProcs
const label numProcs,
[[maybe_unused]] const label comm
)
{
reset();
@ -342,29 +342,46 @@ void Foam::UPstream::commsStruct::reset
}
// * * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<>
Foam::UPstream::commsStruct&
Foam::UList<Foam::UPstream::commsStruct>::operator[](const label procID)
const Foam::UPstream::commsStructList&
Foam::UPstream::commsStructList::null()
{
auto& val = this->v_[procID]; // or this->data()[procID]
static std::unique_ptr<commsStructList> singleton;
if (val.nProcs() != size())
if (!singleton)
{
// Create/update
val.reset(procID, size());
singleton = std::make_unique<commsStructList>();
}
return val;
return *singleton;
}
template<>
const Foam::UPstream::commsStruct&
Foam::UList<Foam::UPstream::commsStruct>::operator[](const label procID) const
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::UPstream::commsStructList::init(const label comm)
{
return const_cast<UList<UPstream::commsStruct>&>(*this).operator[](procID);
comm_ = comm;
tree_.clear();
tree_.resize(UPstream::nProcs(comm));
}
const Foam::UPstream::commsStruct&
Foam::UPstream::commsStructList::get(const label proci) const
{
const UPstream::commsStruct& entry = tree_[proci];
const auto numProcs = tree_.size();
if (entry.nProcs() != numProcs)
{
// Create/update
const_cast<UPstream::commsStruct&>(entry)
.reset(proci, numProcs, comm_);
}
return entry;
}