From: asuraven Date: Fri, 27 Aug 2021 15:34:31 +0000 (+0300) Subject: 0032539: Parallelize distance pair X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=f3f1887f5a605226bd0536534754a01a4d3f56e1;p=occt-copy.git 0032539: Parallelize distance pair --- diff --git a/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx b/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx index cf032def3e..4e062d8b84 100644 --- a/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx +++ b/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx @@ -294,8 +294,8 @@ void BRepExtrema_DistShapeShape::DistanceVertVert(const TopTools_IndexedMapOfSha } for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2) { - const Bnd_Box& aBox1 = theLBox1[anIdx1]; - const Bnd_Box& aBox2 = theLBox2[anIdx2]; + const Bnd_Box& aBox1 = theLBox1[anIdx1-1]; + const Bnd_Box& aBox2 = theLBox2[anIdx2-1]; if (aBox1.IsVoid() || aBox2.IsVoid()) { continue; @@ -354,12 +354,17 @@ void BRepExtrema_DistShapeShape::DistanceVertVert(const TopTools_IndexedMapOfSha Message_ProgressScope aDistScope(theRange, NULL, aNbTasks); for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI) { - VertexTask aTask(aFirstIndex, aFirstIndex + aTaskSize, + if (aCount1 < aFirstIndex + aTaskSize - 1) + { + aTaskSize = aCount1 - aFirstIndex + 1; + } + VertexTask aTask(aFirstIndex, aFirstIndex + aTaskSize-1, &mySolutionsShape1, &mySolutionsShape2, &theMap1, &theMap2, &theLBox1, &theLBox2, aDistScope.Next(), &myIsBreak, &myDistRef, myEps, myMutex); aTaskArray.SetValue(anI, aTask); + aFirstIndex += aTaskSize; } OSD_Parallel::ForEach(aTaskArray.begin(), aTaskArray.end(), VertexFunctor(), Standard_False); @@ -480,11 +485,11 @@ struct DistanceFunctor const BRepExtrema_CheckPair& aPair = theTask.myArray->Value(i); { Standard_Mutex::Sentry aLock(theTask.myMutex.get()); - if (aPair.Distance > *theTask.myDistRef + anEps) - { - *theTask.myIsDone = Standard_True; - break; // early search termination - } + //if (aPair.Distance > *theTask.myDistRef + anEps) + //{ + // *theTask.myIsDone = Standard_True; + // break; // early search termination + //} } const Bnd_Box& aBox1 = theTask.myLBox1->at(aPair.Index1-1); @@ -528,6 +533,130 @@ struct DistanceFunctor } }; +//======================================================================= +//struct : DistancePairTask +//purpose : +//======================================================================= +struct DistancePairTask +{ + DistancePairTask(Standard_Integer theFirtsIndex, + Standard_Integer theLastIndex, + NCollection_Vector* thePairList, + const TopTools_IndexedMapOfShape* theMap1, + const TopTools_IndexedMapOfShape* theMap2, + const std::vector* theLBox1, + const std::vector* theLBox2, + const Message_ProgressRange theRange, + Standard_Boolean* theIsBreak, + Standard_Real theDistRef, + Standard_Real theEps, + Handle(Standard_HMutex) theMutex) + : myFirtsIndex(theFirtsIndex), + myLastIndex(theLastIndex), + myPairList(thePairList), + myMap1(theMap1), + myMap2(theMap2), + myLBox1(theLBox1), + myLBox2(theLBox2), + myRange(theRange), + myIsBreak(theIsBreak), + myDistRef(theDistRef), + myEps(theEps), + myMutex(theMutex) + { + } + + DistancePairTask() + : myFirtsIndex(0), + myLastIndex(0), + myPairList(NULL), + myMap1(NULL), + myMap2(NULL), + myLBox1(NULL), + myLBox2(NULL), + myIsBreak(NULL), + myDistRef(0), + myEps(Precision::Confusion()), + myMutex(NULL) + { + } + + DistancePairTask& DistancePairTask::operator =(const DistancePairTask& theCopy) + { + myFirtsIndex = theCopy.myFirtsIndex; + myLastIndex = theCopy.myLastIndex; + myPairList = theCopy.myPairList; + myMap1 = theCopy.myMap1; + myMap2 = theCopy.myMap2; + myLBox1 = theCopy.myLBox1; + myLBox2 = theCopy.myLBox2; + myRange = theCopy.myRange; + myIsBreak = theCopy.myIsBreak; + myDistRef = theCopy.myDistRef; + myEps = theCopy.myEps; + myMutex = theCopy.myMutex; + return *this; + } + + Standard_Integer myFirtsIndex; + Standard_Integer myLastIndex; + NCollection_Vector* myPairList; + const TopTools_IndexedMapOfShape* myMap1; + const TopTools_IndexedMapOfShape* myMap2; + const std::vector* myLBox1; + const std::vector* myLBox2; + Message_ProgressRange myRange; + Standard_Boolean* myIsBreak; + Standard_Real myDistRef; + Standard_Real myEps; + Handle(Standard_HMutex) myMutex; +}; + +//======================================================================= +//struct : DistancePairFunctor +//purpose : +//======================================================================= +struct DistancePairFunctor +{ + void operator() (DistancePairTask& theTask) const + { + const Standard_Integer aCount1 = theTask.myMap1->Extent(); + const Standard_Integer aCount2 = theTask.myMap2->Extent(); + Message_ProgressScope aScope(theTask.myRange, NULL, theTask.myLastIndex - theTask.myFirtsIndex); + Standard_Real anEpsDist = theTask.myDistRef - theTask.myEps; + + for (Standard_Integer anIdx1 = theTask.myFirtsIndex; anIdx1 <= theTask.myLastIndex; ++anIdx1) + { + if (!aScope.More()) + { + Standard_Atomic_CompareAndSwap((int*) *theTask.myIsBreak, Standard_False, Standard_True); + } + aScope.Next(); + if (*theTask.myIsBreak) + { + break; + } + + for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2) + { + const Bnd_Box& aBox1 = theTask.myLBox1->at(anIdx1 - 1); + const Bnd_Box& aBox2 = theTask.myLBox2->at(anIdx2 - 1); + if (aBox1.IsVoid() || aBox2.IsVoid()) + { + continue; + } + + const Standard_Real aDist = aBox1.Distance(aBox2); + if (aDist < anEpsDist || fabs(aDist - theTask.myDistRef) < theTask.myEps) + { + Standard_Mutex::Sentry aLock(theTask.myMutex.get()); + theTask.myPairList->Append(BRepExtrema_CheckPair(anIdx1, anIdx2, aDist)); + } + } + } + } +}; + //======================================================================= //function : DistanceMapMap //purpose : @@ -540,41 +669,87 @@ void BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShap const Message_ProgressRange& theRange) { NCollection_Vector aPairList; + Message_ProgressScope aTwinScope(theRange, NULL, 2); + + const Standard_Integer aCount1 = theMap1.Extent(); const Standard_Integer aCount2 = theMap2.Extent(); - Message_ProgressScope aTwinScope(theRange, NULL, 2); + + if (myMutex.IsNull()) + { Message_ProgressRange aBoxRange(aTwinScope.Next()); - Message_ProgressScope aBoxScope(aBoxRange, NULL, aCount1); + Message_ProgressScope aBoxScope(aBoxRange, NULL, aCount1); - for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1) + for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1) + { + aBoxScope.Next(); + if (!aBoxScope.More()) + { + throw StdFail_NotDone(); + } + for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2) + { + const Bnd_Box& aBox1 = theLBox1[anIdx1-1]; + const Bnd_Box& aBox2 = theLBox2[anIdx2-1]; + if (aBox1.IsVoid() || aBox2.IsVoid()) + { + continue; + } + + const Standard_Real aDist = aBox1.Distance (aBox2); + if (aDist < myDistRef - myEps || fabs (aDist - myDistRef) < myEps) + { + aPairList.Append (BRepExtrema_CheckPair (anIdx1, anIdx2, aDist)); + } + } + } + } + else { - aBoxScope.Next(); - if (!aBoxScope.More()) + const Standard_Integer aMinTaskSize = 10; + const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool(); + const Standard_Integer aNbThreads = aThreadPool->NbThreads(); + Standard_Integer aNbTasks = aNbThreads * 10; + Standard_Integer aTaskSize = (Standard_Integer) Ceiling((double) aCount1 / aNbTasks); + if (aTaskSize < aMinTaskSize) { - throw StdFail_NotDone(); + aTaskSize = aMinTaskSize; + aNbTasks = (Standard_Integer) Ceiling((double) aCount1 / aTaskSize); } - for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2) + + Standard_Integer aFirstIndex(1); + NCollection_Array1 aTaskArray(0, aNbTasks - 1); + Message_ProgressRange aBoxRange(aTwinScope.Next()); + Message_ProgressScope aDistScope(aBoxRange, NULL, aNbTasks); + for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI) { - const Bnd_Box& aBox1 = theLBox1[anIdx1-1]; - const Bnd_Box& aBox2 = theLBox2[anIdx2-1]; - if (aBox1.IsVoid() || aBox2.IsVoid()) + if (aCount1 < aFirstIndex + aTaskSize - 1) { - continue; + aTaskSize = aCount1 - aFirstIndex + 1; } + DistancePairTask aTask(aFirstIndex, aFirstIndex + aTaskSize-1, + &aPairList, &theMap1, &theMap2, &theLBox1, &theLBox2, + aDistScope.Next(), &myIsBreak, myDistRef, myEps, myMutex); + aTaskArray.SetValue(anI, aTask); + aFirstIndex += aTaskSize; + } + OSD_Parallel::ForEach(aTaskArray.begin(), aTaskArray.end(), DistancePairFunctor(), Standard_False); - const Standard_Real aDist = aBox1.Distance (aBox2); - if (aDist < myDistRef - myEps || fabs (aDist - myDistRef) < myEps) - { - aPairList.Append (BRepExtrema_CheckPair (anIdx1, anIdx2, aDist)); - } + if (myIsBreak) + { + throw StdFail_NotDone(); } } - std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator); - Message_ProgressRange aDistRange(aTwinScope.Next()); if (myMutex.IsNull()) { + std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator); + } + + if (myMutex.IsNull()) + { + Message_ProgressRange aDistRange(aTwinScope.Next()); Message_ProgressScope aDistScope(aDistRange, NULL, aPairList.Size()); for (NCollection_Vector::Iterator aPairIter(aPairList); aPairIter.More(); aPairIter.Next()) @@ -663,6 +838,7 @@ void BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShap } NCollection_Array1 aTaskArray(0, aNbTasks - 1); + Message_ProgressRange aDistRange(aTwinScope.Next()); Message_ProgressScope aDistScope(aDistRange, NULL, aNbTasks); for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI) { @@ -1065,7 +1241,7 @@ Standard_Boolean BRepExtrema_DistShapeShape::Perform(const Message_ProgressRange else myDistRef= 1.e30; //szv:!!! - DistanceVertVert(myMapV1, myMapV2, myBV1, myBV2, aRootScope.Next()); + DistanceVertVert (myMapV1, myMapV2, myBV1, myBV2, aRootScope.Next()); DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2, aRootScope.Next()); DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2, aRootScope.Next()); DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2, aRootScope.Next()); @@ -1125,7 +1301,7 @@ TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution "); - const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N-1]; switch (sol.SupportKind()) { case BRepExtrema_IsVertex : return sol.Vertex(); @@ -1145,7 +1321,7 @@ TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution "); - const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N-1]; switch (sol.SupportKind()) { case BRepExtrema_IsVertex : return sol.Vertex(); @@ -1165,7 +1341,7 @@ void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_ if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution"); - const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N-1]; if (sol.SupportKind() != BRepExtrema_IsOnEdge) throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE"); @@ -1182,7 +1358,7 @@ void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N, Standard if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution"); - const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N-1]; if (sol.SupportKind() != BRepExtrema_IsOnEdge) throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE"); @@ -1199,7 +1375,7 @@ void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N, Standard if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution"); - const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape1[N-1]; if (sol.SupportKind() != BRepExtrema_IsInFace) throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE"); @@ -1216,7 +1392,7 @@ void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N, Standard if (!myIsDone) throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution"); - const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N]; + const BRepExtrema_SolutionElem &sol = mySolutionsShape2[N-1]; if (sol.SupportKind() != BRepExtrema_IsInFace) throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE "); diff --git a/src/BRepExtrema/BRepExtrema_DistanceSS.cxx b/src/BRepExtrema/BRepExtrema_DistanceSS.cxx index 01808b3f23..0ae065e5d6 100644 --- a/src/BRepExtrema/BRepExtrema_DistanceSS.cxx +++ b/src/BRepExtrema/BRepExtrema_DistanceSS.cxx @@ -64,8 +64,7 @@ //------------------------------------------------------------------------------ static Standard_Boolean TRI_SOLUTION (std::vector& SeqSol, const gp_Pnt& Pt) { - const Standard_Integer Nbsol = SeqSol.size(); - for (Standard_Integer i = 1; i <= Nbsol; i++) + for (size_t i = 0; i < SeqSol.size(); i++) { const Standard_Real dst = SeqSol[i].Point().Distance(Pt); if (dst <= Precision::Confusion()) return Standard_False; @@ -83,15 +82,14 @@ static void MIN_SOLUTION (const std::vector& SeqSol1, std::vector& seqSol1, std::vector& seqSol2) { - const Standard_Integer nbSol = SeqSol1.size(); - for (Standard_Integer i = 1; i <= nbSol; i++) + for (size_t i = 0; i < SeqSol1.size(); i++) { const Standard_Real dst1 = SeqSol1[i].Dist(); if (fabs(dst1 - DstRef) < Eps) - { + { seqSol1.push_back(SeqSol1[i]); seqSol2.push_back(SeqSol2[i]); - } + } } }