17#ifdef NF_WITH_MPI_SUPPORT
28inline int bufferHash(
const std::string& str)
32 constexpr int maxTagValue = 32767 - 10;
33 std::size_t tag = std::hash<std::string> {}(str);
35 return (
static_cast<int>(tag) % maxTagValue) + 10;
48class HalfDuplexCommBuffer
56 HalfDuplexCommBuffer() =
default;
61 ~HalfDuplexCommBuffer() =
default;
69 HalfDuplexCommBuffer(MPIEnvironment mpiEnviron, std::vector<size_t> rankCommSize)
70 : mpiEnviron_(mpiEnviron)
72 setCommRankSize<char>(rankCommSize);
80 inline void setMPIEnvironment(MPIEnvironment mpiEnviron) { mpiEnviron_ = mpiEnviron; }
87 inline bool isCommInit()
const {
return tag_ != -1; }
95 template<
typename valueType>
96 void setCommRankSize(std::vector<size_t> rankCommSize)
99 !isCommInit(),
"Communication buffer was initialised by name: " << commName_ <<
"."
102 rankCommSize.size() == mpiEnviron_.sizeRank(),
103 "Rank size mismatch. " << rankCommSize.size() <<
" vs. " << mpiEnviron_.sizeRank()
105 typeSize_ =
sizeof(valueType);
106 rankOffset_.resize(rankCommSize.size() + 1);
107 request_.resize(rankCommSize.size(), MPI_REQUEST_NULL);
108 updateDataSize([&](
const size_t rank) {
return rankCommSize[rank]; },
sizeof(valueType));
117 template<
typename valueType>
118 void initComm(std::string commName)
121 !isCommInit(),
"Communication buffer was initialised by name: " << commName_ <<
"."
123 setType<valueType>();
124 commName_ = commName;
125 tag_ = bufferHash(commName);
133 inline const std::string& getCommName()
const {
return commName_; }
169 template<
typename valueType>
170 std::span<valueType> get(
const size_t rank)
172 NF_DEBUG_ASSERT(isCommInit(),
"Communication buffer is not initialised.");
173 NF_DEBUG_ASSERT(typeSize_ ==
sizeof(valueType),
"Data type (size) mismatch.");
174 return std::span<valueType>(
175 reinterpret_cast<valueType*
>(rankBuffer_.data() + rankOffset_[rank]),
176 (rankOffset_[rank + 1] - rankOffset_[rank]) /
sizeof(valueType)
187 template<
typename valueType>
188 std::span<const valueType> get(
const size_t rank)
const
190 NF_DEBUG_ASSERT(isCommInit(),
"Communication buffer is not initialised.");
191 NF_DEBUG_ASSERT(typeSize_ ==
sizeof(valueType),
"Data type (size) mismatch.");
192 return std::span<const valueType>(
193 reinterpret_cast<const valueType*
>(rankBuffer_.data() + rankOffset_[rank]),
194 (rankOffset_[rank + 1] - rankOffset_[rank]) /
sizeof(valueType)
201 std::string commName_ {
"unassigned"};
202 std::size_t typeSize_ {
sizeof(char)};
203 MPIEnvironment mpiEnviron_;
204 std::vector<MPI_Request> request_;
205 std::vector<char> rankBuffer_;
206 std::vector<std::size_t>
212 template<
typename valueType>
216 !isCommInit(),
"Communication buffer was initialised by name: " << commName_ <<
"."
218 if (0 == (typeSize_ -
sizeof(valueType)))
return;
220 [rankOffset = rankOffset_, typeSize = typeSize_](
const size_t rank)
221 {
return (rankOffset[rank + 1] - rankOffset[rank]) / typeSize; },
225 typeSize_ =
sizeof(valueType);
235 template<
typename func>
236 void updateDataSize(func rankSize, std::size_t newSize)
238 std::size_t dataSize = 0;
239 for (
size_t rank = 0; rank < mpiEnviron_.sizeRank(); ++rank)
241 rankOffset_[rank] = dataSize;
242 dataSize += rankSize(rank) * newSize;
244 rankOffset_.back() = dataSize;
245 if (rankBuffer_.size() < dataSize) rankBuffer_.resize(dataSize);
#define NF_DEBUG_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false (only in debu...