1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0024826: Wrapping of parallelisation algorithms

Simple primitives to parallelize loops type "for" and "foreach" were implemented. The primitives encapsulates complete logic for creating and managing parallel context of loops. Moreover the primitives may be a wrapper for some primitives from 3rd-party library - TBB.

To use it is necessary to implement TBB like interface which is based on functors. For example:

Class Functor
{
public:
  void operator() ([proccesing instance]) const
  {
    //...
  }
};

In the body of the operator () should be implemented thread-safe logic of computations that can be performed in parallel context. If parallelized loop iterates on the collections with direct access by index (such as Vector, Array), it is more efficient to use the primitive ParallelFor (because it has no critical section).

All parts of  OCC code which are using tbb were changed on new primitives.

0024826: Wrapping of parallelisation algorithms

Small fix.
This commit is contained in:
msv
2015-02-05 15:49:35 +03:00
committed by bugmaster
parent a61133c8c7
commit c7b59798ca
34 changed files with 837 additions and 683 deletions

View File

@@ -62,6 +62,8 @@
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <OSD_Parallel.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <NCollection_IncAllocator.hxx>
@@ -71,11 +73,6 @@
#include <vector>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/parallel_for_each.h>
#endif
#define UVDEFLECTION 1.e-05
IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscret, Standard_Transient)
@@ -176,20 +173,7 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
aFaces.push_back(aFace);
}
#ifdef HAVE_TBB
if ( myInParallel )
{
tbb::parallel_for_each(aFaces.begin(), aFaces.end(), *this);
}
else
{
#endif
std::vector<TopoDS_Face>::const_iterator anIt(aFaces.begin());
for (; anIt != aFaces.end(); anIt++)
Process(*anIt);
#ifdef HAVE_TBB
}
#endif
OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myInParallel);
}

View File

@@ -16,6 +16,7 @@
#include <BRepMesh_IncrementalMesh.hxx>
#include <OSD_Parallel.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
@@ -52,11 +53,6 @@
#include <GCPnts_TangentialDeflection.hxx>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/parallel_for_each.h>
#endif
namespace
{
//! Default flag to control parallelization for BRepMesh_IncrementalMesh
@@ -223,19 +219,7 @@ void BRepMesh_IncrementalMesh::update()
update(aFaceIt.Value());
// Mesh faces
#ifdef HAVE_TBB
if (myInParallel)
{
tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesh);
}
else
{
#endif
for (aFaceIt.Init(myFaces); aFaceIt.More(); aFaceIt.Next())
myMesh->Process(aFaceIt.Value());
#ifdef HAVE_TBB
}
#endif
OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myInParallel);
commit();
clear();
@@ -577,12 +561,7 @@ Standard_Integer BRepMesh_IncrementalMesh::Discret(
//=======================================================================
Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
{
#ifdef HAVE_TBB
return IS_IN_PARALLEL;
#else
// no alternative parallelization yet - flag has no meaning
return Standard_False;
#endif
}
//=======================================================================

View File

@@ -30,12 +30,8 @@
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepMesh_WireInterferenceChecker.hxx>
#include <OSD_Parallel.hxx>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#endif
//=======================================================================
//function : Selector::Constructor
@@ -196,27 +192,18 @@ void BRepMesh_WireChecker::ReCompute(BRepMesh::HClassifier& theClassifier)
BRepMesh::Array1OfSegmentsTree aWiresBiPoints(1, aNbWires);
fillSegmentsTree(aDWires, aWiresBiPoints);
#ifdef HAVE_TBB
Standard_Mutex aWireMutex;
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints,
&myStatus, &aWireMutex);
if (myIsInParallel && aNbWires > 1)
{
// check wires in parallel threads using TBB
tbb::parallel_for(tbb::blocked_range<Standard_Integer>(1, aNbWires + 1),
aIntChecker);
// Check wires in parallel threads.
Standard_Mutex aWireMutex;
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus, &aWireMutex);
OSD_Parallel::For(1, aNbWires + 1, aIntChecker);
}
else
{
#else
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus);
#endif
for (Standard_Integer i = 1; i <= aNbWires; ++i)
aIntChecker(i);
#ifdef HAVE_TBB
OSD_Parallel::For(1, aNbWires + 1, aIntChecker, Standard_True);
}
#endif
if (myStatus == BRepMesh_SelfIntersectingWire)
return;

View File

@@ -20,7 +20,6 @@
// TODO: remove this variable after implementation of LoopChecker2d.
static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5;
#ifdef HAVE_TBB
//=======================================================================
//function : Constructor
//purpose :
@@ -35,30 +34,6 @@ BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
{
}
//=======================================================================
//function : Checker's body
//purpose :
//=======================================================================
void BRepMesh_WireInterferenceChecker::operator ()(
const tbb::blocked_range<Standard_Integer>& theWireRange) const
{
for (Standard_Integer i = theWireRange.begin(); i != theWireRange.end(); ++i)
this->operator ()(i);
}
#else
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus)
: myWires (theWires),
myStatus(theStatus)
{
}
#endif
//=======================================================================
//function : Checker's body
//purpose :
@@ -75,11 +50,9 @@ void BRepMesh_WireInterferenceChecker::operator ()(
for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
// Break execution in case if flag was raised by another thread.
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
const BRepMesh::SegmentsTree& aWireSegTree2 =
@@ -93,11 +66,9 @@ void BRepMesh_WireInterferenceChecker::operator ()(
Standard_Integer aSegmentId1 = aWireSegments1->Lower();
for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
aSelector.Clear();
aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
@@ -112,11 +83,9 @@ void BRepMesh_WireInterferenceChecker::operator ()(
const Standard_Integer aSelectedNb = aSelector.IndicesNb();
for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
const Standard_Integer aSegmentId2 = aSelected(aBndIt);
const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
@@ -154,10 +123,9 @@ void BRepMesh_WireInterferenceChecker::operator ()(
continue;
}
#ifdef HAVE_TBB
Standard_Mutex::Sentry aSentry(myMutex);
#endif
*myStatus = BRepMesh_SelfIntersectingWire;
return;
}
}

View File

@@ -21,11 +21,6 @@
#include <BRepMesh_WireChecker.hxx>
#include <BRepMesh_Status.hxx>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/blocked_range.h>
#endif
//! Auxilary class implementing functionality for
//! checking interference between two discretized wires.
class BRepMesh_WireInterferenceChecker
@@ -43,7 +38,6 @@ public:
Same
};
#ifdef HAVE_TBB
//! Constructor
//! @param theWires wires that should be checked.
//! @param theStatus shared flag to set status of the check.
@@ -51,19 +45,7 @@ public:
BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex);
//! Checker's body.
//! @param theWireRange range of wires to be checked.
void operator ()(const tbb::blocked_range<Standard_Integer>& theWireRange) const;
#else
//! Constructor
//! @param theWires wires that should be checked.
//! @param theStatus shared flag to set status of the check.
BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus);
#endif
Standard_Mutex* theMutex = NULL);
//! Checker's body.
//! @param theWireId Id of discretized wire to be checked.
@@ -79,10 +61,7 @@ private:
private:
const BRepMesh::Array1OfSegmentsTree& myWires;
BRepMesh_Status* myStatus;
#ifdef HAVE_TBB
Standard_Mutex* myMutex;
#endif
};
#endif