From: oan Date: Wed, 18 Apr 2018 08:21:00 +0000 (+0300) Subject: 0029177: Foundation Classes - Adapt BVH package for use of OSD_Parallel X-Git-Tag: V7_4_0_beta~292 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=da555fc2ab912f4c8dd8945b62b011f3dbf845e9 0029177: Foundation Classes - Adapt BVH package for use of OSD_Parallel Explicit calls to TBB in BVH_DistanceField, BVH_LinearBuilder and BVH_RadixSorter have been replaced. Task functors have been separated on execution and state parts for the sake of usage by OSD_Parallel. --- diff --git a/src/BVH/BVH_DistanceField.lxx b/src/BVH/BVH_DistanceField.lxx index f4ddd367b2..a83a2a3653 100644 --- a/src/BVH/BVH_DistanceField.lxx +++ b/src/BVH/BVH_DistanceField.lxx @@ -14,18 +14,7 @@ // commercial license or contractual agreement. #include - -#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 will - // run on Windows NT 4.0 at least - #if defined(_WIN32) && !defined(_WIN32_WINNT) - #define _WIN32_WINNT 0x0501 - #endif - - #include -#endif +#include // ======================================================================= // function : BVH_DistanceField @@ -407,8 +396,6 @@ namespace BVH #undef BVH_DOT3 -#ifdef HAVE_TBB - //! Tool object for parallel construction of distance field (uses Intel TBB). template class BVH_ParallelDistanceFieldBuilder @@ -430,14 +417,12 @@ public: // } - void operator() (const tbb::blocked_range& theRange) const + void operator() (const Standard_Integer theIndex) const { - myOutField->BuildSlices (*myGeometry, theRange.begin(), theRange.end()); + myOutField->BuildSlices (*myGeometry, theIndex, theIndex + 1); } }; -#endif - // ======================================================================= // function : BuildSlices // purpose : Performs building of distance field for the given Z slices @@ -510,16 +495,7 @@ Standard_Boolean BVH_DistanceField::Build (BVH_Geometry& theGeometry myVoxelSize.y() = (myCornerMax.y() - myCornerMin.y()) / myDimensionY; myVoxelSize.z() = (myCornerMax.z() - myCornerMin.z()) / myDimensionZ; -#ifdef HAVE_TBB - - tbb::parallel_for (tbb::blocked_range (0, myDimensionZ), - BVH_ParallelDistanceFieldBuilder (this, &theGeometry)); - -#else - - BuildSlices (theGeometry, 0, myDimensionZ); - -#endif + OSD_Parallel::For (0, myDimensionZ, BVH_ParallelDistanceFieldBuilder (this, &theGeometry)); return Standard_True; } diff --git a/src/BVH/BVH_LinearBuilder.hxx b/src/BVH/BVH_LinearBuilder.hxx index 35e20d46f4..9f0a2233bb 100644 --- a/src/BVH/BVH_LinearBuilder.hxx +++ b/src/BVH/BVH_LinearBuilder.hxx @@ -211,92 +211,79 @@ namespace BVH return 0; } -#ifdef HAVE_TBB - - //! TBB task for parallel bounds updating. template - class UpdateBoundTask: public tbb::task + struct BoundData { - - BVH_Set* mySet; //!< Set of geometric objects + BVH_Set * mySet; //!< Set of geometric objects BVH_Tree* myBVH; //!< BVH tree built over the set Standard_Integer myNode; //!< BVH node to update bounding box Standard_Integer myLevel; //!< Level of the processed BVH node Standard_Integer* myHeight; //!< Height of the processed BVH node + }; + //! Task for parallel bounds updating. + template + class UpdateBoundTask + { public: - //! Creates new TBB parallel bound update task. - UpdateBoundTask (BVH_Set* theSet, - BVH_Tree* theBVH, - Standard_Integer theNode, - Standard_Integer theLevel, - Standard_Integer* theHeight) - : mySet (theSet), myBVH (theBVH), myNode (theNode), myLevel (theLevel), myHeight (theHeight) {} - //! Executes the task. - tbb::task* execute() + void operator()(const BoundData& theData) const { - if (myBVH->IsOuter (myNode) || myLevel > 2) + if (theData.myBVH->IsOuter (theData.myNode) || theData.myLevel > 2) { - *myHeight = BVH::UpdateBounds (mySet, myBVH, myNode); + *theData.myHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, theData.myNode); } else { Standard_Integer aLftHeight = 0; Standard_Integer aRghHeight = 0; - const Standard_Integer aLftChild = myBVH->NodeInfoBuffer()[myNode].y(); - const Standard_Integer aRghChild = myBVH->NodeInfoBuffer()[myNode].z(); + const Standard_Integer aLftChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].y(); + const Standard_Integer aRghChild = theData.myBVH->NodeInfoBuffer()[theData.myNode].z(); - Standard_Integer aCount = 1; - tbb::task_list aList; - if (!myBVH->IsOuter (aLftChild)) + std::vector > aList; + aList.reserve (2); + if (!theData.myBVH->IsOuter (aLftChild)) { - ++aCount; - aList.push_back (*new ( allocate_child() ) - UpdateBoundTask (mySet, myBVH, aLftChild, myLevel + 1, &aLftHeight)); + BoundData aBoundData = {theData.mySet, theData.myBVH, aLftChild, theData.myLevel + 1, &aLftHeight}; + aList.push_back (aBoundData); } else { - aLftHeight = BVH::UpdateBounds (mySet, myBVH, aLftChild); + aLftHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, aLftChild); } - if (!myBVH->IsOuter (aRghChild)) + if (!theData.myBVH->IsOuter (aRghChild)) { - ++aCount; - aList.push_back (*new( allocate_child() ) - UpdateBoundTask (mySet, myBVH, aRghChild, myLevel + 1, &aRghHeight)); + BoundData aBoundData = {theData.mySet, theData.myBVH, aRghChild, theData.myLevel + 1, &aRghHeight}; + aList.push_back (aBoundData); } else { - aRghHeight = BVH::UpdateBounds (mySet, myBVH, aRghChild); + aRghHeight = BVH::UpdateBounds (theData.mySet, theData.myBVH, aRghChild); } - if (aCount > 1) + if (!aList.empty()) { - set_ref_count (aCount); - spawn_and_wait_for_all (aList); + OSD_Parallel::ForEach (aList.begin (), aList.end (), UpdateBoundTask ()); } - typename BVH_Box::BVH_VecNt aLftMinPoint = myBVH->MinPointBuffer()[aLftChild]; - typename BVH_Box::BVH_VecNt aLftMaxPoint = myBVH->MaxPointBuffer()[aLftChild]; - typename BVH_Box::BVH_VecNt aRghMinPoint = myBVH->MinPointBuffer()[aRghChild]; - typename BVH_Box::BVH_VecNt aRghMaxPoint = myBVH->MaxPointBuffer()[aRghChild]; + typename BVH_Box::BVH_VecNt aLftMinPoint = theData.myBVH->MinPointBuffer()[aLftChild]; + typename BVH_Box::BVH_VecNt aLftMaxPoint = theData.myBVH->MaxPointBuffer()[aLftChild]; + typename BVH_Box::BVH_VecNt aRghMinPoint = theData.myBVH->MinPointBuffer()[aRghChild]; + typename BVH_Box::BVH_VecNt aRghMaxPoint = theData.myBVH->MaxPointBuffer()[aRghChild]; BVH::BoxMinMax::CwiseMin (aLftMinPoint, aRghMinPoint); BVH::BoxMinMax::CwiseMax (aLftMaxPoint, aRghMaxPoint); - myBVH->MinPointBuffer()[myNode] = aLftMinPoint; - myBVH->MaxPointBuffer()[myNode] = aLftMaxPoint; + theData.myBVH->MinPointBuffer()[theData.myNode] = aLftMinPoint; + theData.myBVH->MaxPointBuffer()[theData.myNode] = aLftMaxPoint; - *myHeight = Max (aLftHeight, aRghHeight) + 1; + *theData.myHeight = Max (aLftHeight, aRghHeight) + 1; } - return NULL; } }; - -#endif } // ======================================================================= @@ -331,21 +318,9 @@ void BVH_LinearBuilder::Build (BVH_Set* theSet, theBVH->MaxPointBuffer().resize (theBVH->NodeInfoBuffer().size()); Standard_Integer aHeight = 0; - -#ifdef HAVE_TBB - - // Note: Although TBB tasks are allocated using placement - // new, we do not need to delete them explicitly - BVH::UpdateBoundTask& aRootTask = *new ( tbb::task::allocate_root() ) - BVH::UpdateBoundTask (theSet, theBVH, 0, 0, &aHeight); - - tbb::task::spawn_root_and_wait (aRootTask); - -#else - - aHeight = BVH::UpdateBounds (theSet, theBVH, 0); - -#endif + BVH::BoundData aBoundData = { theSet, theBVH, 0, 0, &aHeight }; + BVH::UpdateBoundTask aBoundTask; + aBoundTask (aBoundData); BVH_Builder::updateDepth (theBVH, aHeight); } diff --git a/src/BVH/BVH_RadixSorter.hxx b/src/BVH/BVH_RadixSorter.hxx index 4425a74231..b0a8b06950 100644 --- a/src/BVH/BVH_RadixSorter.hxx +++ b/src/BVH/BVH_RadixSorter.hxx @@ -20,21 +20,10 @@ #include #include #include +#include #include -#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 will - // run on Windows NT 4.0 at least - #if defined(_WIN32) && !defined(_WIN32_WINNT) - #define _WIN32_WINNT 0x0501 - #endif - - #include -#endif - //! Pair of Morton code and primitive ID. typedef std::pair BVH_EncodedLink; @@ -113,21 +102,21 @@ namespace BVH private: - //! TBB functor class to run sorting. - struct Functor + //! Structure defining sorting range. + struct SortRange { LinkIterator myStart; //!< Start element of exclusive sorting range LinkIterator myFinal; //!< Final element of exclusive sorting range Standard_Integer myDigit; //!< Bit number used for partition operation + }; - //! Creates new sorting functor. - Functor (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) - : myStart (theStart), myFinal (theFinal), myDigit (theDigit) {} - + //! Functor class to run sorting in parallel. + struct Functor + { //! Runs sorting function for the given range. - void operator() () const + void operator()(const SortRange& theRange) const { - RadixSorter::Sort (myStart, myFinal, myDigit); + RadixSorter::Sort (theRange.myStart, theRange.myFinal, theRange.myDigit); } }; @@ -135,7 +124,6 @@ namespace BVH static void Sort (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit) { - #ifdef HAVE_TBB if (theDigit < 24) { BVH::RadixSorter::perform (theStart, theFinal, theDigit); @@ -143,12 +131,13 @@ namespace BVH else { LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit)); - tbb::parallel_invoke (Functor (theStart, anOffset, theDigit - 1), - Functor (anOffset, theFinal, theDigit - 1)); + SortRange aSplits[2] = { + {theStart, anOffset, theDigit - 1}, + {anOffset, theFinal, theDigit - 1} + }; + + OSD_Parallel::ForEach (std::begin (aSplits), std::end (aSplits), Functor ()); } - #else - BVH::RadixSorter::perform (theStart, theFinal, theDigit); - #endif } protected: