diff --git a/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C index efdb248655..d896f3958b 100644 --- a/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C +++ b/src/OpenFOAM/db/IOstreams/Fstreams/masterOFstream.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2017 OpenFOAM Foundation - Copyright (C) 2020-2023 OpenCFD Ltd. + Copyright (C) 2020-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,7 +29,7 @@ License #include "masterOFstream.H" #include "OFstream.H" #include "OSspecific.H" -#include "PstreamBuffers.H" +#include "Pstream.H" #include "masterUncollatedFileOperation.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -41,9 +41,9 @@ void Foam::masterOFstream::checkWrite std::streamsize len ) { - if (!len) + if (!str || !(len > 0)) { - // Can probably skip all of this if there is nothing to write + // Can skip everything if there is nothing to write return; } @@ -63,9 +63,7 @@ void Foam::masterOFstream::checkWrite << exit(FatalIOError); } - // Use writeRaw() instead of writeQuoted(string,false) to output - // characters directly. - + // Write characters directly to std::ostream os.writeRaw(str, len); if (!os.good()) @@ -77,24 +75,29 @@ void Foam::masterOFstream::checkWrite } -void Foam::masterOFstream::checkWrite -( - const fileName& fName, - const std::string& s -) -{ - checkWrite(fName, s.data(), s.length()); -} - - void Foam::masterOFstream::commit() { - if (UPstream::parRun()) + // Take ownership of serialized content + DynamicList charData(OCharStream::release()); + + if (!UPstream::parRun()) { + // Write (non-empty) data + checkWrite(pathName_, charData); + } + else + { + // Ignore content if not writing + if (!writeOnProc_) + { + charData.clear(); + } + List filePaths(UPstream::nProcs(comm_)); filePaths[UPstream::myProcNo(comm_)] = pathName_; Pstream::gatherList(filePaths, UPstream::msgType(), comm_); + // Test for identical output paths bool uniform = ( UPstream::master(comm_) @@ -105,69 +108,136 @@ void Foam::masterOFstream::commit() if (uniform) { + // Identical file paths - write on master if (UPstream::master(comm_) && writeOnProc_) { - checkWrite(pathName_, this->str()); + checkWrite(pathName_, charData); } - - this->reset(); return; } // Different files - PstreamBuffers pBufs(comm_); + // --------------- + // + // Non-sparse (most ranks have writeOnProc_ == true), + // so gather sizes first and use PEX-like handling, + // with polling for when data becomes available. + // + // Could also consider double buffering + write to reduce + // memory overhead. - if (!UPstream::master(comm_)) - { - if (writeOnProc_) - { - // Send buffer to master - string s(this->str()); + // Or int64_t + const label dataSize = + ( + (UPstream::is_subrank(comm_) && writeOnProc_) + ? charData.size() + : 0 + ); - UOPstream os(UPstream::masterNo(), pBufs); - os.write(s.data(), s.length()); - } - this->reset(); // Done with contents - } - - pBufs.finishedGathers(); + const labelList recvSizes + ( + UPstream::listGatherValues