diff --git a/applications/test/globalIndex3/Test-globalIndex3.cxx b/applications/test/globalIndex3/Test-globalIndex3.cxx index d6ae4a658e..19beee6239 100644 --- a/applications/test/globalIndex3/Test-globalIndex3.cxx +++ b/applications/test/globalIndex3/Test-globalIndex3.cxx @@ -345,8 +345,8 @@ static void reportOffsets(const globalIndex& gi) UPstream::broadcast ( - allOffsets.data_bytes(), - allOffsets.size_bytes(), + allOffsets.data(), + allOffsets.size(), interNodeComm ); } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H index ef8acb773b..1563a8da48 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H @@ -109,6 +109,15 @@ public: const int communicator = UPstream::worldComm ); + //- Broadcast fixed-list content (contiguous or non-contiguous) to all + //- communicator ranks. Does nothing in \b non-parallel. + template + static void broadcast + ( + FixedList& list, + const int communicator = UPstream::worldComm + ); + //- Broadcast multiple items to all communicator ranks. //- Does nothing in \b non-parallel. template diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx index 23193de0dd..447d268544 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx @@ -43,7 +43,6 @@ void Foam::Pstream::broadcast } else if constexpr (is_contiguous_v) { - // Note: contains parallel guard internally UPstream::broadcast ( reinterpret_cast(&value), @@ -65,6 +64,37 @@ void Foam::Pstream::broadcast } +template +void Foam::Pstream::broadcast +( + FixedList& list, + const int communicator +) +{ + if (!UPstream::is_parallel(communicator)) + { + return; + } + else if constexpr (is_contiguous_v) + { + // Size is known and identical on all ranks + UPstream::broadcast(list.data(), list.size(), communicator); + } + else + { + // Non-contiguous content - serialize it + if (UPstream::master(communicator)) + { + OPBstream::send(list, communicator); + } + else + { + IPBstream::recv(list, communicator); + } + } +} + + template void Foam::Pstream::broadcasts ( @@ -77,8 +107,15 @@ void Foam::Pstream::broadcasts { return; } + else if constexpr (!sizeof...(values) && is_contiguous_v) + { + // A single-value and contiguous + UPstream::broadcast(&value, 1, communicator); + } else { + // Non-contiguous data, or multiple data - needs serialization + if (UPstream::master(communicator)) { OPBstream::sends @@ -129,19 +166,10 @@ void Foam::Pstream::broadcastList communicator ); - if (UPstream::is_subrank(communicator)) - { - list.resize_nocopy(len); - } - if (len) { - UPstream::broadcast - ( - list.data_bytes(), - list.size_bytes(), - communicator - ); + // Only broadcast non-empty content + UPstream::broadcast(list.data(), list.size(), communicator); } } else @@ -150,13 +178,28 @@ void Foam::Pstream::broadcastList if (UPstream::master(communicator)) { - OPBstream os(communicator); - os << list; + if (list.empty()) + { + // Do not serialize if empty. + // Just broadcast zero-size in a form that IPBstream can expect + OPBstream::send(Foam::zero{}, communicator); + } + else + { + OPBstream::send(list, communicator); + } } else { IPBstream is(communicator); - is >> list; + if (is.remaining() > 0) // Received a non-empty buffer + { + is >> list; + } + else + { + list.clear(); + } } } } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H index 2373facaa8..40643472e2 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H @@ -1720,16 +1720,16 @@ public: // Broadcast Functions - //- Broadcast buffer contents to all processes in given communicator. - //- The sizes must match on all processes. + //- Broadcast buffer contents (contiguous types), from rank=0 + //- to all ranks. The sizes must match on all processes. // For \b non-parallel : do nothing. // \return True on success - static bool broadcast + template + inline static bool broadcast ( - char* buf, - const std::streamsize bufSize, - const label communicator, - const int rootProcNo = masterNo() + Type* buffer, + std::streamsize count, + const int communicator ); diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx index 844b203446..076b6c0e54 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx @@ -27,6 +27,44 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +bool Foam::UPstream::broadcast +( + Type* buffer, + std::streamsize count, + const int communicator +) +{ + // Likely no reason to check for nullptr + if (!UPstream::is_parallel(communicator)) + { + // Nothing to do - ignore + return true; + } + else if constexpr (!is_contiguous_v) + { + // Also report parameters to silence compiler warnings about unused + FatalErrorInFunction + << "Invalid for non-contiguous data types." + << " buffer:" << (buffer != nullptr) + << " count:" << count + << Foam::abort(FatalError); + return false; + } + else + { + // Use element or component type (or byte-wise) for data type + return UPstream::mpi_broadcast + ( + buffer, // The data or cmpt pointer + UPstream_dataType::size(count), + UPstream_dataType::datatype_id, + communicator + ); + } +} + + template Foam::List Foam::UPstream::allGatherValues ( diff --git a/src/OpenFOAM/parallel/globalIndex/globalIndex.C b/src/OpenFOAM/parallel/globalIndex/globalIndex.C index 95f64b161c..12113485a4 100644 --- a/src/OpenFOAM/parallel/globalIndex/globalIndex.C +++ b/src/OpenFOAM/parallel/globalIndex/globalIndex.C @@ -319,12 +319,7 @@ bool Foam::globalIndex::splitNodeOffsets allOffsets.resize_nocopy(numProc+1); } - UPstream::broadcast - ( - allOffsets.data_bytes(), - allOffsets.size_bytes(), - interNodeComm - ); + UPstream::broadcast(allOffsets.data(), allOffsets.size(), interNodeComm); if (FOAM_UNLIKELY(allOffsets.empty())) diff --git a/src/Pstream/dummy/UPstreamBroadcast.C b/src/Pstream/dummy/UPstreamBroadcast.C index ae2825a51b..0e87b5b50b 100644 --- a/src/Pstream/dummy/UPstreamBroadcast.C +++ b/src/Pstream/dummy/UPstreamBroadcast.C @@ -42,19 +42,4 @@ bool Foam::UPstream::mpi_broadcast } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -bool Foam::UPstream::broadcast -( - char* buf, - const std::streamsize bufSize, - const label comm, - const int rootProcNo -) -{ - // Nothing to do - ignore - return true; -} - - // ************************************************************************* // diff --git a/src/Pstream/mpi/UPstreamBroadcast.C b/src/Pstream/mpi/UPstreamBroadcast.C index 686fb230ad..91f4b1abfc 100644 --- a/src/Pstream/mpi/UPstreamBroadcast.C +++ b/src/Pstream/mpi/UPstreamBroadcast.C @@ -92,24 +92,4 @@ bool Foam::UPstream::mpi_broadcast } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -bool Foam::UPstream::broadcast -( - char* buf, - const std::streamsize count, - const label communicator, - const int rootProcNo -) -{ - return UPstream::mpi_broadcast - ( - buf, - count, - UPstream::dataTypes::type_byte, - communicator - ); -} - - // ************************************************************************* //