]> OCCT Git - occt-copy.git/commitdiff
0032539: Parallelize distance pair CR32539
authorasuraven <andrey.suravenkov@opencascade.com>
Fri, 27 Aug 2021 15:34:31 +0000 (18:34 +0300)
committerasuraven <andrey.suravenkov@opencascade.com>
Mon, 30 Aug 2021 13:00:59 +0000 (16:00 +0300)
src/BRepExtrema/BRepExtrema_DistShapeShape.cxx
src/BRepExtrema/BRepExtrema_DistanceSS.cxx

index cf032def3ee25d4cb1df517258aeed569b4b94a1..4e062d8b84cfa79d45596f03b1513d292b4b8c9f 100644 (file)
@@ -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<BRepExtrema_CheckPair>* thePairList,
+                   const TopTools_IndexedMapOfShape* theMap1,
+                   const TopTools_IndexedMapOfShape* theMap2,
+                   const std::vector<Bnd_Box>* theLBox1,
+                   const std::vector<Bnd_Box>* 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<BRepExtrema_CheckPair>* myPairList;
+  const TopTools_IndexedMapOfShape* myMap1;
+  const TopTools_IndexedMapOfShape* myMap2;
+  const std::vector<Bnd_Box>* myLBox1;
+  const std::vector<Bnd_Box>* 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<BRepExtrema_CheckPair> 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<DistancePairTask> 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<BRepExtrema_CheckPair>::Iterator aPairIter(aPairList);
          aPairIter.More(); aPairIter.Next())
@@ -663,6 +838,7 @@ void BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShap
       }
 
       NCollection_Array1<DistanceTask> 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 ");
   
index 01808b3f2328d6cdca61ea074e8d4aac152ea3f3..0ae065e5d6f094f861f1433bcd33b01130bdc3a0 100644 (file)
@@ -64,8 +64,7 @@
 //------------------------------------------------------------------------------
 static Standard_Boolean TRI_SOLUTION (std::vector<BRepExtrema_SolutionElem>& 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<BRepExtrema_SolutionElem>& SeqSol1,
                           std::vector<BRepExtrema_SolutionElem>& seqSol1,
                           std::vector<BRepExtrema_SolutionElem>& 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]);
-       }
+         }
   }
 }