1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-18 14:27:39 +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

@@ -0,0 +1,174 @@
// Created by: Peter KURNEV
// Copyright (c) 1999-2013 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _BOPDS_Col_HeaderFile
#define _BOPDS_Col_HeaderFile
#include <Standard_Macro.hxx>
#include <Standard_NotImplemented.hxx>
#include <OSD_Parallel.hxx>
#include <NCollection_DataMap.hxx>
//
// 1. Implementation of Functors/Starters
//
// 1.1. Pure version
//
//=======================================================================
//class : BOPCol_Functor
//purpose :
//=======================================================================
template <class TypeSolver, class TypeSolverVector>
class BOPCol_Functor
{
public:
//! Constructor.
explicit BOPCol_Functor(TypeSolverVector& theSolverVec)
: mySolvers(theSolverVec) {}
//! Defines functor interface.
void operator() (const Standard_Integer theIndex) const
{
TypeSolver& aSolver = mySolvers(theIndex);
aSolver.Perform();
}
private:
BOPCol_Functor(const BOPCol_Functor&);
BOPCol_Functor& operator= (const BOPCol_Functor&);
private:
TypeSolverVector& mySolvers;
};
//=======================================================================
//class : BOPCol_Cnt
//purpose :
//=======================================================================
template <class TypeFunctor, class TypeSolverVector>
class BOPCol_Cnt
{
public:
static void Perform( const Standard_Boolean isRunParallel,
TypeSolverVector& theSolverVector )
{
TypeFunctor aFunctor(theSolverVector);
OSD_Parallel::For(0, theSolverVector.Extent(), aFunctor, !isRunParallel);
}
};
//
// 1.2. Context dependent version
//
//=======================================================================
//class : BOPCol_ContextFunctor
//purpose :
//=======================================================================
template <class TypeSolver, class TypeSolverVector,
class TypeContext, typename TN>
class BOPCol_ContextFunctor
{
//! Auxiliary thread ID hasher.
struct Hasher
{
static Standard_Integer HashCode(const Standard_ThreadId theKey,
const Standard_Integer Upper)
{
return ::HashCode(reinterpret_cast<Standard_Address>(theKey), Upper);
}
static Standard_Boolean IsEqual(const Standard_ThreadId theKey1,
const Standard_ThreadId theKey2)
{
return theKey1 == theKey2;
}
};
typedef NCollection_DataMap<Standard_ThreadId, TypeContext, Hasher> ContextMap;
public:
//! Constructor
explicit BOPCol_ContextFunctor( TypeSolverVector& theVector )
: mySolverVector(theVector) {}
//! Binds main thread context
void SetContext( TypeContext& theContext )
{
myContexts.Bind(OSD_Thread::Current(), theContext);
}
//! Returns current thread context
TypeContext& GetThreadContext() const
{
const Standard_ThreadId aThreadID = OSD_Thread::Current();
if ( myContexts.IsBound(aThreadID) )
{
TypeContext& aContext = myContexts(aThreadID);
if ( aContext.IsNull() == Standard_False )
return aContext;
}
// Create new context
TypeContext aContext = new TN
( NCollection_BaseAllocator::CommonBaseAllocator() );
Standard_Mutex::Sentry aLocker(myMutex);
myContexts.Bind(aThreadID, aContext);
return myContexts(aThreadID);
}
//! Defines functor interface
void operator()( const Standard_Integer theIndex ) const
{
TypeContext& aContext = GetThreadContext();
TypeSolver& aSolver = mySolverVector(theIndex);
aSolver.SetContext(aContext);
aSolver.Perform();
}
private:
BOPCol_ContextFunctor(const BOPCol_ContextFunctor&);
BOPCol_ContextFunctor& operator= (const BOPCol_ContextFunctor&);
private:
TypeSolverVector& mySolverVector;
mutable ContextMap myContexts;
mutable Standard_Mutex myMutex;
};
//=======================================================================
//class : BOPCol_ContextCnt
//purpose :
//=======================================================================
template <class TypeFunctor, class TypeSolverVector, class TypeContext>
class BOPCol_ContextCnt
{
public:
static void Perform( const Standard_Boolean isRunParallel,
TypeSolverVector& theSolverVector,
TypeContext& theContext )
{
TypeFunctor aFunctor(theSolverVector);
aFunctor.SetContext(theContext);
OSD_Parallel::For(0, theSolverVector.Extent(), aFunctor, !isRunParallel);
}
};
#endif

View File

@@ -1,248 +0,0 @@
// Created by: Peter KURNEV
// Copyright (c) 1999-2013 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _BOPDS_Col_HeaderFile
#define _BOPDS_Col_HeaderFile
#include <Standard_Macro.hxx>
#include <Standard_NotImplemented.hxx>
#ifdef HAVE_TBB
// On Windows, function TryEnterCriticalSection has appeared in Windows NT
// and is surrounded by #ifdef in MS VC++ 7.1 headers.
// Thus to use it we need to define appropriate macro saying that we wil
// run on Windows NT 4.0 at least
#if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT))
#define _WIN32_WINNT 0x0501
#endif
#include <tbb/tbb.h>
using namespace tbb;
#define flexible_range blocked_range
#define flexible_for parallel_for
#else // not HAVE_TBB
#define flexible_range serial_range
#define flexible_for serial_for
//=======================================================================
//class : serial_range
//purpose :
//=======================================================================
template <class Type> class serial_range {
public:
serial_range(const Type& aBegin,
const Type& aEnd)
: myBegin(aBegin), myEnd(aEnd) {
}
//
~serial_range() {
}
//
const Type& begin() const{
return myBegin;
}
//
const Type& end() const{
return myEnd;
};
//
protected:
Type myBegin;
Type myEnd;
};
//=======================================================================
//function : serial_for
//purpose :
//=======================================================================
template<typename Range, typename Body>
static void serial_for( const Range& range, const Body& body ) {
body.operator()(range);
};
#endif // not HAVE_TBB
//
// 2. Implementation of Functors/Starters
//
// 2.1. Pure version
//
//=======================================================================
//class : BOPCol_TBBFunctor
//purpose :
//=======================================================================
template <class TypeSolver,
class TypeSolverVector> class BOPCol_TBBFunctor {
public:
BOPCol_TBBFunctor(TypeSolverVector& aV)
: myPV(&aV) {
}
//
~BOPCol_TBBFunctor() {
}
//
void operator()( const flexible_range<Standard_Integer>& aBR ) const{
Standard_Integer i, iBeg, iEnd;
//
TypeSolverVector& aV=*myPV;
//
iBeg=aBR.begin();
iEnd=aBR.end();
for(i=iBeg; i!=iEnd; ++i) {
TypeSolver& aSolver=aV(i);
//
aSolver.Perform();
}
}
//
protected:
TypeSolverVector* myPV;
};
//=======================================================================
//class : BOPCol_TBBCnt
//purpose :
//=======================================================================
template <class TypeFunctor,
class TypeSolverVector> class BOPCol_TBBCnt {
public:
//-------------------------------
// Perform
Standard_EXPORT
static void Perform(const Standard_Boolean bRunParallel,
TypeSolverVector& aV) {
//
TypeFunctor aFunctor(aV);
Standard_Integer aNb=aV.Extent();
//
if (bRunParallel) {
#ifdef HAVE_TBB
try {
flexible_for(flexible_range<Standard_Integer>(0,aNb), aFunctor);
}
//
catch( captured_exception& ) {
Standard_NotImplemented::Raise("");
}
catch( ... ) {
Standard_NotImplemented::Raise("");
}
#else // not HAVE_TBB
flexible_for(flexible_range<Standard_Integer>(0,aNb), aFunctor);
#endif
}
else {
aFunctor.operator()(flexible_range<Standard_Integer>(0,aNb));
}
}
};
//
// 2.2. Context dependent version
//
//=======================================================================
//class : BOPCol_TBBContextFunctor
//purpose :
//=======================================================================
template <class TypeSolver,
class TypeSolverVector,
class TypeContext,
typename TN> class BOPCol_TBBContextFunctor {
public:
BOPCol_TBBContextFunctor(TypeSolverVector& aV)
: myPV(&aV) {
}
//
~BOPCol_TBBContextFunctor() {
}
//
void SetContext(TypeContext& aCtx) {
myContext=aCtx;
}
//
void operator()( const flexible_range<Standard_Integer>& aBR ) const{
Standard_Integer i, iBeg, iEnd;
TypeContext aCtx;
//
if (myContext.IsNull()) {
aCtx=new TN
(NCollection_BaseAllocator::CommonBaseAllocator());
}
else {
aCtx=myContext;
}
//
TypeSolverVector& aV=*myPV;
//
iBeg=aBR.begin();
iEnd=aBR.end();
for(i=iBeg; i!=iEnd; ++i) {
TypeSolver& aSolver=aV(i);
//
aSolver.SetContext(aCtx);
aSolver.Perform();
}
}
//
protected:
TypeSolverVector* myPV;
TypeContext myContext;
//
};
//=======================================================================
//class : BOPCol_TBBContextCnt
//purpose :
//=======================================================================
template <class TypeFunctor,
class TypeSolverVector,
class TypeContext> class BOPCol_TBBContextCnt {
public:
//-------------------------------
// Perform
Standard_EXPORT
static void Perform(const Standard_Boolean bRunParallel,
TypeSolverVector& aV,
TypeContext& aCtx) {
//
TypeFunctor aFunctor(aV);
Standard_Integer aNb=aV.Extent();
//
if (bRunParallel) {
#ifdef HAVE_TBB
try {
flexible_for(flexible_range<Standard_Integer>(0,aNb), aFunctor);
}
//
catch(captured_exception& ) {
//cout<<" captured_exception: " << ex.what() << endl;
Standard_NotImplemented::Raise("");
}
catch( ... ) {
Standard_NotImplemented::Raise("");
}
#else // not HAVE_TBB
flexible_for(flexible_range<Standard_Integer>(0,aNb), aFunctor);
#endif
}
else {
aFunctor.SetContext(aCtx);
aFunctor.operator()(flexible_range<Standard_Integer>(0,aNb));
}
}
};
#endif

View File

@@ -28,7 +28,7 @@ BOPCol_SequenceOfReal.hxx
BOPCol_DataMapOfIntegerShape.hxx
BOPCol_IndexedDataMapOfIntegerListOfInteger.hxx
BOPCol_IndexedDataMapOfShapeInteger.hxx
BOPCol_TBB.hxx
BOPCol_Parallel.hxx
BOPCol_NCVector.hxx
BOPCol_BoxBndTree.hxx