From 3dee3438d5129358e5ff56166b799b77cc27b252 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 21 Jun 2023 20:38:44 +0200 Subject: [PATCH] ENH: improve send/recv robustness in the presence of processorCyclic (#2814) - the changes introduced in f215ad15d176 aim to reduce unnecessary point-to-point communication. However, if there are also processorCyclic boundaries involved, there are multiple connections between any two processors, so simply skipping empty sends will cause synchronization problems. Eg, On the send side: patch0to1_a is zero (doesn't send) and patch0to1_b does send (to the same processor). On the receive side: patch1to0_a receives the data intended for patch1to0_b ! Remedy ====== Simply stream all of send data into PstreamBuffers (regardless if empty or non-empty) but track the sends as a bit operation: empty (0) or non-empty (1) Reset the buffer slots that were only sent empty data. This adds an additional local overhead but avoids communication as much as possible. --- .../polyMesh/globalMeshData/globalPoints.C | 52 +++++++++++----- .../polyMesh/syncTools/syncToolsTemplates.C | 62 ++++++++++++++++--- .../fvMesh/fvMeshSubset/fvMeshSubset.C | 34 +++++----- .../algorithms/MeshWave/FaceCellWave.C | 60 +++++++++++++----- .../algorithms/PointEdgeWave/PointEdgeWave.C | 31 ++++++++-- .../isoAdvection/isoAdvection.C | 14 +++-- 6 files changed, 187 insertions(+), 66 deletions(-) diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C index 50443ca893..361c64c051 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalPoints.C @@ -487,6 +487,9 @@ void Foam::globalPoints::sendPatchPoints const polyBoundaryMesh& patches = mesh_.boundaryMesh(); const labelPairList& patchInfo = globalTransforms_.patchTransformSign(); + // Reset send/recv information + pBufs.clear(); + // Information to send: // The patch face @@ -499,6 +502,19 @@ void Foam::globalPoints::sendPatchPoints DynamicList allInfo; + // Reduce communication by only sending non-zero data, + // but with multiply-connected processor/processor + // (eg, processorCyclic) also need to send zero information + // to keep things synchronised + + // Has non-zero data sent + Map isActiveSend(0); + + if (UPstream::parRun()) + { + isActiveSend.resize(2*min(patches.size(),pBufs.nProcs())); + } + forAll(patches, patchi) { const polyPatch& pp = patches[patchi]; @@ -508,7 +524,7 @@ void Foam::globalPoints::sendPatchPoints if ( - (Pstream::parRun() && isA(pp)) + (UPstream::parRun() && isA(pp)) && (mergeSeparated || patchInfo[patchi].first() == -1) ) { @@ -561,21 +577,32 @@ void Foam::globalPoints::sendPatchPoints } - if (!patchFaces.empty()) + // Send to neighbour { - // Send to neighbour + UOPstream toNbr(nbrProci, pBufs); + toNbr << patchFaces << indexInFace << allInfo; + + // Record if send is required (data are non-zero) + isActiveSend(nbrProci) |= int(!patchFaces.empty()); + if (debug) { - Pout<< " Sending from " << pp.name() << " to proc:" + Pout<< "Sending from " << pp.name() << " to proc:" << nbrProci << " point information:" << patchFaces.size() << endl; } - - UOPstream toNeighbour(nbrProci, pBufs); - toNeighbour << patchFaces << indexInFace << allInfo; } } } + + // Eliminate unnecessary sends + forAllConstIters(isActiveSend, iter) + { + if (!iter.val()) + { + pBufs.clearSend(iter.key()); + } + } } @@ -606,7 +633,7 @@ void Foam::globalPoints::receivePatchPoints if ( - (Pstream::parRun() && isA(pp)) + (UPstream::parRun() && isA(pp)) && (mergeSeparated || patchInfo[patchi].first() == -1) ) { @@ -615,6 +642,7 @@ void Foam::globalPoints::receivePatchPoints if (!pBufs.recvDataCount(nbrProci)) { + // Nothing to receive continue; } @@ -623,8 +651,8 @@ void Foam::globalPoints::receivePatchPoints List nbrInfo; { - UIPstream fromNeighbour(nbrProci, pBufs); - fromNeighbour >> patchFaces >> indexInFace >> nbrInfo; + UIPstream fromNbr(nbrProci, pBufs); + fromNbr >> patchFaces >> indexInFace >> nbrInfo; } if (debug) @@ -929,8 +957,6 @@ void Foam::globalPoints::calculateSharedPoints // Do one exchange iteration to get neighbour points. { - pBufs.clear(); - sendPatchPoints ( mergeSeparated, @@ -962,8 +988,6 @@ void Foam::globalPoints::calculateSharedPoints do { - pBufs.clear(); - sendPatchPoints ( mergeSeparated, diff --git a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C index f24116864f..0cd73e8a6a 100644 --- a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C @@ -130,7 +130,15 @@ void Foam::syncTools::syncPointMap DynamicList