diff --git a/applications/test/globalIndex/Test-globalIndex.C b/applications/test/globalIndex/Test-globalIndex.C index b7bfe0a3f2..c743c1316b 100644 --- a/applications/test/globalIndex/Test-globalIndex.C +++ b/applications/test/globalIndex/Test-globalIndex.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2021 OpenCFD Ltd. + Copyright (C) 2021-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -198,15 +198,15 @@ int main(int argc, char *argv[]) // Do the brute-force method as well : collect all cell centres on all // processors - pointField allCcs(globalNumbering.size()); - globalNumbering.gather - ( - Pstream::worldComm, - Pstream::procID(Pstream::worldComm), - mesh.cellCentres(), - allCcs - ); + + Info<< "Gathered/scattered cell centres:" << endl; + + labelPair inOut; + pointField allCcs(globalNumbering.gather(mesh.cellCentres())); + inOut[0] = allCcs.size(); Pstream::scatter(allCcs); + inOut[1] = allCcs.size(); + Pout<< " " << inOut << endl; // Compare forAll(ccs, i) @@ -239,10 +239,13 @@ int main(int argc, char *argv[]) Info<< "local-sizes: " << globalPointsPtr().sizes() << nl; - UIndirectList procPoints(mesh.points(), uniqueMeshPointLabels); - pointField patchPoints; - - globalPointsPtr().gather(procPoints, patchPoints); + pointField patchPoints + ( + globalPointsPtr().gather + ( + UIndirectList(mesh.points(), uniqueMeshPointLabels) + ) + ); Info<< "gathered point field = " << patchPoints.size() << " points\n"; } diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C index 434bd4200a..c556cc2b01 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2021 OpenCFD Ltd. + Copyright (C) 2018-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -176,6 +176,12 @@ void Foam::globalIndex::bin } +void Foam::globalIndex::reset(const label localSize) +{ + reset(localSize, Pstream::msgType(), UPstream::worldComm, true); +} + + void Foam::globalIndex::reset ( const label localSize, @@ -189,6 +195,8 @@ void Foam::globalIndex::reset if (len) { // Seed with localSize, zero elsewhere (for non-parallel branch) + // NB: can consider UPstream::listGatherValues + labelList localSizes(len, Zero); localSizes[Pstream::myProcNo(comm)] = localSize; @@ -202,6 +210,7 @@ void Foam::globalIndex::reset } else { + // Nothing to do offsets_.clear(); } } diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H index c5ad93b81e..674c2ef2da 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2018-2021 OpenCFD Ltd. + Copyright (C) 2018-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,14 +35,14 @@ Description label globalFacei = globalFaces.toGlobal(facei); SourceFiles - globalIndexI.H globalIndex.C + globalIndexI.H globalIndexTemplates.C \*---------------------------------------------------------------------------*/ -#ifndef globalIndex_H -#define globalIndex_H +#ifndef Foam_globalIndex_H +#define Foam_globalIndex_H #include "Pstream.H" #include "CompactListList.H" @@ -175,7 +175,7 @@ public: //- Reset from local size. // Does communication with default communicator and message tag. - inline void reset(const label localSize); + void reset(const label localSize); //- Reset from local size. // Does communication with given communicator and message tag, @@ -377,10 +377,10 @@ public: // Other - // Gather + // Gather (helpers) //- Collect data in processor order on master (== procIDs[0]). - // Offsets needed on master only. + // \note offsets needed on master only. template static void gather ( @@ -394,7 +394,7 @@ public: ); //- Collect indirect data in processor order on master - // Offsets needed on master only. + // \note offsets needed on master only. template static void gather ( @@ -407,8 +407,21 @@ public: const Pstream::commsTypes = Pstream::commsTypes::scheduled ); + //- Inplace collect in processor order on master (== procIDs[0]). + // \note offsets needed on master only. + template + static void gather + ( + const labelUList& offsets, + const label comm, //!< communicator + const ProcIDsContainer& procIDs, + List& fld, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking + ); + //- Collect data in processor order on master (== procIDs[0]). - // Offsets needed on master only. + // \note the globalIndex offsets needed on master only. template void gather ( @@ -424,45 +437,8 @@ public: gather(offsets_, comm, procIDs, fld, allFld, tag, commsType); } - //- Collect data in processor order on master. - // Does communication with default communicator and message tag. - template - void gather - ( - const UList& fld, - List& allFld, - const int tag = UPstream::msgType(), - const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, - const label comm = UPstream::worldComm //!< communicator - ) const; - - //- Collect data indirectly in processor order on master. - // Does communication with default communicator and message tag. - template - void gather - ( - const IndirectListBase& fld, - List& allFld, - const int tag = UPstream::msgType(), - const Pstream::commsTypes = Pstream::commsTypes::scheduled, - const label comm = UPstream::worldComm //!< communicator - ) const; - //- Inplace collect in processor order on master (== procIDs[0]). - //- Needs offsets only on master. - template - static void gather - ( - const labelUList& offsets, - const label comm, //!< communicator - const ProcIDsContainer& procIDs, - List& fld, - const int tag = UPstream::msgType(), - const Pstream::commsTypes = Pstream::commsTypes::nonBlocking - ); - - //- Inplace collect in processor order on master (== procIDs[0]). - //- Needs offsets only on master. + // \note the globalIndex offsets needed on master only. template void gather ( @@ -477,11 +453,68 @@ public: gather(offsets_, comm, procIDs, fld, tag, commsType); } - //- Inplace collect data in processor order on master - // Does communication with default communicator and message tag. - // After the gather, the field is zero-sized on the slaves. + + // Gather + + //- Collect data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. template void gather + ( + const UList& sendData, + List& allData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator + ) const; + + //- Collect data indirectly in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + template + void gather + ( + const IndirectListBase& sendData, + List& allData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::scheduled, + const label comm = UPstream::worldComm //!< communicator + ) const; + + //- Collect data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + // + // \return output (master), zero-sized on non-master + template> + OutputContainer gather + ( + const UList& sendData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator + ) const; + + //- Collect data indirectly in processor order on master. + // Communication with default/specified communicator, message tag. + // + // \return output (master), zero-sized on non-master + template> + OutputContainer gather + ( + const IndirectListBase& sendData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::scheduled, + const label comm = UPstream::worldComm //!< communicator + ) const; + + //- Inplace collect data in processor order on master + //- (in serial: a no-op). + // Communication with default/specified communicator, message tag. + // After the gather, the field is zero-sized on the slaves. + template + void gatherInplace ( List& fld, const int tag = UPstream::msgType(), @@ -490,19 +523,27 @@ public: ) const; //- Collect \em contiguous data using a MPI_Gatherv call + //- (in serial: performs a simple copy). + // Communication with default/specified communicator. // \attention The nProcs for globalIndex and communicator // must match!! + // + // The allData is output (master), zero-sized on non-master template> void mpiGather ( const UList& sendData, - OutputContainer& allValues, + OutputContainer& allData, const label comm = UPstream::worldComm //!< communicator ) const; //- Collect \em contiguous data using a MPI_Gatherv call + //- (in serial: performs a simple copy). + // Communication with default/specified communicator. // \attention The nProcs for globalIndex and communicator // must match!! + // + // \return output (master), zero-sized on non-master template> OutputContainer mpiGather ( @@ -510,33 +551,139 @@ public: const label comm = UPstream::worldComm //!< communicator ) const; + //- Inplace collect \em contiguous data using a MPI_Gatherv call + //- (in serial: a no-op). + // Communication with default/specified communicator. + // \attention The nProcs for globalIndex and communicator + // must match!! + // + // After the gather, the field is zero-sized on non-master. + template + void mpiGatherInplace + ( + List& fld, + const label comm = UPstream::worldComm //!< communicator + ) const; - //- Collect data in processor order on master. - // Does communication with default communicator and message tag. + + // Gather Operations + + //- Collect \em contiguous data using a MPI_Gatherv call + //- (in serial: performs a simple copy). + // Communication with default/specified communicator. + // + // The allData is output (master), zero-sized on non-master + template> + static void mpiGatherOp + ( + const UList& sendData, + OutputContainer& allData, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Collect \em contiguous data using a MPI_Gatherv call + //- (in serial: performs a simple copy). + // Communication with default/specified communicator. + // + // \return output (master), zero-sized on non-master + template> + static OutputContainer mpiGatherOp + ( + const UList& sendData, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Inplace collect \em contiguous data using a MPI_Gatherv call + //- (in serial: a no-op). + // Communication with default/specified communicator. + // + // After the gather, the field is zero-sized on non-master. + template + static void mpiGatherInplaceOp + ( + List& fld, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Collect data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + // + // The allFld is output (master), zero-sized on non-master template static void gatherOp ( - const UList& fld, - List& allFld, + const UList& sendData, + List& allData, const int tag = UPstream::msgType(), - const Pstream::commsTypes = Pstream::commsTypes::nonBlocking + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Collect data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + // + // The allFld is output (master), zero-sized on non-master + template + static void gatherOp + ( + const IndirectListBase& sendData, + List& allData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Collect and return data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + // + // \return output (master), zero-sized on non-master + template> + static OutputContainer gatherOp + ( + const UList& sendData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator + ); + + //- Collect and return data in processor order on master + //- (in serial: performs a simple copy). + // Communication with default/specified communicator, message tag. + // + // \return output (master), zero-sized on non-master + template> + static OutputContainer gatherOp + ( + const IndirectListBase& sendData, + const int tag = UPstream::msgType(), + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator ); //- Inplace collect data in processor order on master - // Does communication with default communicator and message tag. + //- (in serial: a no-op). + // Communication with default/specified communicator, message tag. + // // After the gather, the field is zero-sized on the slaves. template - static void gatherOp + static void gatherInplaceOp ( List& fld, const int tag = UPstream::msgType(), - const Pstream::commsTypes = Pstream::commsTypes::nonBlocking + const Pstream::commsTypes = Pstream::commsTypes::nonBlocking, + const label comm = UPstream::worldComm //!< communicator ); // Scatter - //- Distribute data in processor order. Requires fld to be sized! + //- Distribute data in processor order. + // Requires fld to be correctly sized! + // Communication with default/specified communicator, message tag. + // \note offsets needed on master only. template static void scatter ( @@ -549,7 +696,10 @@ public: const Pstream::commsTypes = Pstream::commsTypes::nonBlocking ); - //- Distribute data in processor order. Requires fld to be sized! + //- Distribute data in processor order. + // Requires fld to be correctly sized! + // Communication with default/specified communicator, message tag. + // \note the globalIndex offsets needed on master only. template void scatter ( @@ -565,8 +715,10 @@ public: scatter(offsets_, comm, procIDs, allFld, fld, tag, commsType); } - //- Distribute data in processor order. Requires fld to be sized! - // Does communication with default communicator and message tag. + //- Distribute data in processor order. + // Requires fld to be correctly sized! + // Communication with default/specified communicator, message tag. + // \note the globalIndex offsets needed on master only. template void scatter ( @@ -582,6 +734,7 @@ public: //- Get (potentially remote) data. //- Elements required given as global indices + // Communication with default/specified communicator, message tag. template void get ( diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexI.H b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexI.H index 28118c373d..3fb6d1948e 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexI.H +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexI.H @@ -154,12 +154,6 @@ inline Foam::label Foam::globalIndex::size() const } -inline void Foam::globalIndex::reset(const label localSize) -{ - reset(localSize, Pstream::msgType(), UPstream::worldComm, true); -} - - inline Foam::label Foam::globalIndex::offset(const label proci) const { return offsets_[proci]; diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexTemplates.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexTemplates.C index f8676ace53..380a6383b7 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndexTemplates.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2013-2017 OpenFOAM Foundation - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -68,12 +68,10 @@ Foam::globalIndex::calcListOffsets } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - template void Foam::globalIndex::gather ( - const labelUList& off, + const labelUList& off, // needed on master only const label comm, const ProcIDsContainer& procIDs, const UList& fld, @@ -82,6 +80,8 @@ void Foam::globalIndex::gather const Pstream::commsTypes commsType ) { + // low-level: no parRun guard + if ( !is_contiguous::value @@ -94,6 +94,8 @@ void Foam::globalIndex::gather // Could also warn and change to scheduled etc... } + const label startOfRequests = UPstream::nRequests(); + if (Pstream::myProcNo(comm) == procIDs[0]) { allFld.resize_nocopy(off.last()); @@ -106,53 +108,12 @@ void Foam::globalIndex::gather SubList(allFld, off[1]-off[0], off[0]) = SubList(fld, off[1]-off[0]); - if - ( - commsType == Pstream::commsTypes::scheduled - || commsType == Pstream::commsTypes::blocking - ) + for (label i = 1; i < procIDs.size(); ++i) { - for (label i = 1; i < procIDs.size(); ++i) + SubList procSlot(allFld, off[i+1]-off[i], off[i]); + + if (is_contiguous::value) { - SubList procSlot(allFld, off[i+1]-off[i], off[i]); - - if (is_contiguous::value) - { - IPstream::read - ( - commsType, - procIDs[i], - procSlot.data_bytes(), - procSlot.size_bytes(), - tag, - comm - ); - } - else - { - IPstream fromProc - ( - commsType, - procIDs[i], - 0, - tag, - comm - ); - fromProc >> procSlot; - } - } - } - else - { - // nonBlocking && is_contiguous == true (already checked) - - const label startOfRequests = Pstream::nRequests(); - - // Set up reads - for (label i = 1; i < procIDs.size(); ++i) - { - SubList procSlot(allFld, off[i+1]-off[i], off[i]); - IPstream::read ( commsType, @@ -163,51 +124,24 @@ void Foam::globalIndex::gather comm ); } - - // Wait for all to finish - Pstream::waitRequests(startOfRequests); - } - } - else - { - if - ( - commsType == Pstream::commsTypes::scheduled - || commsType == Pstream::commsTypes::blocking - ) - { - if (is_contiguous::value) - { - OPstream::write - ( - commsType, - procIDs[0], - fld.cdata_bytes(), - fld.size_bytes(), - tag, - comm - ); - } else { - OPstream toMaster + IPstream fromProc ( commsType, - procIDs[0], + procIDs[i], 0, tag, comm ); - toMaster << fld; + fromProc >> procSlot; } } - else + } + else + { + if (is_contiguous::value) { - // nonBlocking && is_contiguous == true (already checked) - - const label startOfRequests = Pstream::nRequests(); - - // Set up write OPstream::write ( commsType, @@ -217,10 +151,25 @@ void Foam::globalIndex::gather tag, comm ); - - // Wait for all to finish - Pstream::waitRequests(startOfRequests); } + else + { + OPstream toMaster + ( + commsType, + procIDs[0], + 0, + tag, + comm + ); + toMaster << fld; + } + } + + if (commsType == Pstream::commsTypes::nonBlocking) + { + // Wait for all to finish + UPstream::waitRequests(startOfRequests); } } @@ -228,7 +177,7 @@ void Foam::globalIndex::gather template void Foam::globalIndex::gather ( - const labelUList& off, + const labelUList& off, // needed on master only const label comm, const UList& procIDs, const IndirectListBase& fld, @@ -237,6 +186,8 @@ void Foam::globalIndex::gather const Pstream::commsTypes commsType ) { + // low-level: no parRun guard + if (commsType == Pstream::commsTypes::nonBlocking) { WarningInFunction @@ -289,55 +240,10 @@ void Foam::globalIndex::gather } -template -void Foam::globalIndex::gather -( - const UList& fld, - List& allFld, - const int tag, - const Pstream::commsTypes commsType, - const label comm -) const -{ - gather - ( - comm, - UPstream::procID(comm), - fld, - allFld, - tag, - commsType - ); -} - - -template -void Foam::globalIndex::gather -( - const IndirectListBase& fld, - List& allFld, - const int tag, - const Pstream::commsTypes commsType, - const label comm -) const -{ - gather - ( - offsets_, - comm, - UPstream::procID(comm), - fld, - allFld, - tag, - commsType - ); -} - - template void Foam::globalIndex::gather ( - const labelUList& off, + const labelUList& off, // needed on master only const label comm, const ProcIDsContainer& procIDs, List& fld, @@ -345,19 +251,123 @@ void Foam::globalIndex::gather const Pstream::commsTypes commsType ) { - List allFld; + // low-level: no parRun guard - gather(off, comm, procIDs, fld, allFld, tag, commsType); + List allData; + + gather(off, comm, procIDs, fld, allData, tag, commsType); if (Pstream::myProcNo(comm) == procIDs[0]) { - fld.transfer(allFld); + fld.transfer(allData); } } +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template void Foam::globalIndex::gather +( + const UList& sendData, + List& allData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) const +{ + if (UPstream::parRun()) + { + gather + ( + offsets_, // needed on master only + comm, + UPstream::procID(comm), + sendData, + allData, + tag, + commsType + ); + if (!UPstream::master(comm)) + { + allData.clear(); // safety: zero-size on non-master + } + } + else + { + // Serial: direct copy + allData = sendData; + } +} + + +template +void Foam::globalIndex::gather +( + const IndirectListBase& sendData, + List& allData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) const +{ + if (UPstream::parRun()) + { + gather + ( + offsets_, // needed on master only + comm, + UPstream::procID(comm), + sendData, + allData, + tag, + commsType + ); + if (!UPstream::master(comm)) + { + allData.clear(); // safety: zero-size on non-master + } + } + else + { + // Serial: direct copy + allData = List(sendData); + } +} + + +template +OutputContainer Foam::globalIndex::gather +( + const UList& sendData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) const +{ + OutputContainer allData; + gather(sendData, allData, tag, commsType, comm); + return allData; +} + + +template +OutputContainer Foam::globalIndex::gather +( + const IndirectListBase& sendData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) const +{ + OutputContainer allData; + gather(sendData, allData, tag, commsType, comm); + return allData; +} + + +template +void Foam::globalIndex::gatherInplace ( List& fld, const int tag, @@ -365,26 +375,30 @@ void Foam::globalIndex::gather const label comm ) const { - List allFld; - - gather - ( - comm, - UPstream::procID(comm), - fld, - allFld, - tag, - commsType - ); - - if (Pstream::master(comm)) + if (UPstream::parRun()) { - fld.transfer(allFld); - } - else - { - fld.clear(); + List allData; + + gather + ( + comm, + UPstream::procID(comm), + fld, + allData, + tag, + commsType + ); + + if (UPstream::master(comm)) + { + fld.transfer(allData); + } + else + { + fld.clear(); // zero-size on non-master + } } + // Serial: (no-op) } @@ -392,10 +406,16 @@ template void Foam::globalIndex::mpiGather ( const UList& sendData, - OutputContainer& allValues, + OutputContainer& allData, const label comm ) const { + if (!UPstream::parRun()) + { + // Serial: direct copy + allData = sendData; + return; + } if (!is_contiguous::value) { FatalErrorInFunction @@ -403,29 +423,25 @@ void Foam::globalIndex::mpiGather << abort(FatalError); } - const label proci = Pstream::myProcNo(comm); - - const globalIndex& globalAddr = *this; - - // Must be the same as Pstream::nProcs(comm), at least on master!! - const label nproc = globalAddr.nProcs(); - auto nSendBytes = sendData.size_bytes(); - // Respect local size information so that we can request - // 0 entries to be sent on master - - if (proci < nproc && !globalAddr.localSize(proci)) - { - nSendBytes = 0; - } - List recvSizes; List recvOffsets; - if (Pstream::master(comm)) + if (UPstream::master(comm)) { - allValues.resize_nocopy(globalAddr.size()); + const globalIndex& globalAddr = *this; + + // Must be the same as Pstream::nProcs(comm), at least on master!! + const label nproc = globalAddr.nProcs(); + + // Allow request of 0 entries to be sent on master + if (!globalAddr.localSize(0)) + { + nSendBytes = 0; + } + + allData.resize_nocopy(globalAddr.size()); recvSizes.resize(nproc); recvOffsets.resize(nproc+1); @@ -439,14 +455,14 @@ void Foam::globalIndex::mpiGather } else { - allValues.clear(); + allData.clear(); // safety: zero-size on non-master } UPstream::gather ( sendData.cdata_bytes(), nSendBytes, - allValues.data_bytes(), + allData.data_bytes(), recvSizes, recvOffsets, comm @@ -461,41 +477,210 @@ OutputContainer Foam::globalIndex::mpiGather const label comm ) const { - OutputContainer allValues; - mpiGather(sendData, allValues, comm); - return allValues; + OutputContainer allData; + mpiGather(sendData, allData, comm); + return allData; +} + + +template +void Foam::globalIndex::mpiGatherInplace +( + List& fld, + const label comm +) const +{ + if (UPstream::parRun()) + { + List allData; + mpiGather(fld, allData, comm); + + if (UPstream::master(comm)) + { + fld.transfer(allData); + } + else + { + fld.clear(); // zero-size on non-master + } + } + // Serial: (no-op) +} + + +template +void Foam::globalIndex::mpiGatherOp +( + const UList& sendData, + OutputContainer& allData, + const label comm +) +{ + if (UPstream::parRun()) + { + // Gather sizes - only needed on master + globalIndex + ( + UPstream::listGatherValues(sendData.size(), comm), + accessType::SIZES + ).mpiGather(sendData, allData, comm); + } + else + { + // Serial: direct copy + allData = sendData; + } +} + + +template +OutputContainer Foam::globalIndex::mpiGatherOp +( + const UList& sendData, + const label comm +) +{ + OutputContainer allData; + mpiGatherOp(sendData, allData, comm); + return allData; +} + + +template +void Foam::globalIndex::mpiGatherInplaceOp +( + List& fld, + const label comm +) +{ + if (UPstream::parRun()) + { + List allData; + mpiGatherOp(fld, allData, comm); + + if (UPstream::master(comm)) + { + fld.transfer(allData); + } + else + { + fld.clear(); // zero-size on non-master + } + } + // Serial: (no-op) } template void Foam::globalIndex::gatherOp ( - const UList& fld, - List& allFld, + const UList& sendData, + List& allData, const int tag, - const Pstream::commsTypes commsType + const Pstream::commsTypes commsType, + const label comm ) { - globalIndex(fld.size()).gather(fld, allFld, tag, commsType); + if (UPstream::parRun()) + { + // Gather sizes - only needed on master + globalIndex + ( + UPstream::listGatherValues(sendData.size(), comm), + accessType::SIZES + ).gather(sendData, allData, tag, commsType, comm); + } + else + { + // Serial: direct copy + allData = sendData; + } +} + + +template +void Foam::globalIndex::gatherOp +( + const IndirectListBase& sendData, + List& allData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) +{ + if (UPstream::parRun()) + { + // Gather sizes - only needed on master + globalIndex + ( + UPstream::listGatherValues(sendData.size(), comm), + accessType::SIZES + ).gather(sendData, allData, tag, commsType, comm); + } + else + { + // Serial: direct copy + allData = List(sendData); + } +} + + +template +OutputContainer Foam::globalIndex::gatherOp +( + const UList& sendData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) +{ + OutputContainer allData; + gatherOp(sendData, allData, tag, commsType, comm); + return allData; +} + + +template +OutputContainer Foam::globalIndex::gatherOp +( + const IndirectListBase& sendData, + const int tag, + const Pstream::commsTypes commsType, + const label comm +) +{ + OutputContainer allData; + gatherOp(sendData, allData, tag, commsType, comm); + return allData; } template -void Foam::globalIndex::gatherOp +void Foam::globalIndex::gatherInplaceOp ( List& fld, const int tag, - const Pstream::commsTypes commsType + const Pstream::commsTypes commsType, + const label comm ) { - globalIndex(fld.size()).gather(fld, tag, commsType); + if (UPstream::parRun()) + { + // Gather sizes - only needed on master + globalIndex + ( + UPstream::listGatherValues(fld.size(), comm), + accessType::SIZES + ).gather(fld, tag, commsType, comm); + } + // Serial: (no-op) } template void Foam::globalIndex::scatter ( - const labelUList& off, + const labelUList& off, // needed on master only const label comm, const ProcIDsContainer& procIDs, const UList& allFld, @@ -516,6 +701,8 @@ void Foam::globalIndex::scatter // Could also warn and change to scheduled etc... } + const label startOfRequests = UPstream::nRequests(); + if (Pstream::myProcNo(comm) == procIDs[0]) { const SubList localSlot(allFld, off[1]-off[0], off[0]); @@ -525,53 +712,12 @@ void Foam::globalIndex::scatter fld.deepCopy(localSlot); } - if - ( - commsType == Pstream::commsTypes::scheduled - || commsType == Pstream::commsTypes::blocking - ) + for (label i = 1; i < procIDs.size(); ++i) { - for (label i = 1; i < procIDs.size(); ++i) + const SubList procSlot(allFld, off[i+1]-off[i], off[i]); + + if (is_contiguous::value) { - const SubList procSlot(allFld, off[i+1]-off[i], off[i]); - - if (is_contiguous::value) - { - OPstream::write - ( - commsType, - procIDs[i], - procSlot.cdata_bytes(), - procSlot.size_bytes(), - tag, - comm - ); - } - else - { - OPstream toProc - ( - commsType, - procIDs[i], - 0, - tag, - comm - ); - toProc << procSlot; - } - } - } - else - { - // nonBlocking && is_contiguous == true (already checked) - - const label startOfRequests = Pstream::nRequests(); - - // Set up writes - for (label i = 1; i < procIDs.size(); ++i) - { - const SubList procSlot(allFld, off[i+1]-off[i], off[i]); - OPstream::write ( commsType, @@ -582,51 +728,24 @@ void Foam::globalIndex::scatter comm ); } - - // Wait for all to finish - Pstream::waitRequests(startOfRequests); - } - } - else - { - if - ( - commsType == Pstream::commsTypes::scheduled - || commsType == Pstream::commsTypes::blocking - ) - { - if (is_contiguous::value) - { - IPstream::read - ( - commsType, - procIDs[0], - fld.data_bytes(), - fld.size_bytes(), - tag, - comm - ); - } else { - IPstream fromMaster + OPstream toProc ( commsType, - procIDs[0], + procIDs[i], 0, tag, comm ); - fromMaster >> fld; + toProc << procSlot; } } - else + } + else + { + if (is_contiguous::value) { - // nonBlocking && is_contiguous == true (already checked) - - const label startOfRequests = Pstream::nRequests(); - - // Set up read IPstream::read ( commsType, @@ -636,10 +755,25 @@ void Foam::globalIndex::scatter tag, comm ); - - // Wait for all to finish - Pstream::waitRequests(startOfRequests); } + else + { + IPstream fromMaster + ( + commsType, + procIDs[0], + 0, + tag, + comm + ); + fromMaster >> fld; + } + } + + if (commsType == Pstream::commsTypes::nonBlocking) + { + // Wait for all to finish + UPstream::waitRequests(startOfRequests); } } @@ -654,16 +788,19 @@ void Foam::globalIndex::scatter const label comm ) const { - scatter - ( - offsets_, - comm, - UPstream::procID(comm), - allFld, - fld, - tag, - commsType - ); + // TBD: protection and special handling for serial? + { + scatter + ( + offsets_, // needed on master only + comm, + UPstream::procID(comm), + allFld, + fld, + tag, + commsType + ); + } }