[bos #38500 #41499 #41496][EDF] Make body fitting thread safe. Implement new parallel for function with std::threads to compute the elements and include needed lock_guard mutex wrapper in problematic function ::Add of B_Intersection and Hexahedron class.

This commit is contained in:
cconopoima 2024-06-18 09:55:50 +01:00
parent 27c8af8c6e
commit a4d1fae96a

View File

@ -98,7 +98,9 @@
#include <gp_Sphere.hxx> #include <gp_Sphere.hxx>
#include <gp_Torus.hxx> #include <gp_Torus.hxx>
//STD
#include <limits> #include <limits>
#include <mutex>
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
@ -116,12 +118,15 @@
#define _WIN32_WINNT 0x0A00 #define _WIN32_WINNT 0x0A00
#endif #endif
#include <thread>
#include <algorithm>
#include <tbb/parallel_for.h> #include <tbb/parallel_for.h>
//#include <tbb/enumerable_thread_specific.h>
#endif #endif
using namespace std; using namespace std;
using namespace SMESH; using namespace SMESH;
std::mutex _eMutex;
std::mutex _bMutex;
//============================================================================= //=============================================================================
/*! /*!
@ -351,7 +356,7 @@ namespace
mutable vector< TGeomID > _faceIDs; mutable vector< TGeomID > _faceIDs;
B_IntersectPoint(): _node(NULL) {} B_IntersectPoint(): _node(NULL) {}
bool Add( const vector< TGeomID >& fIDs, const SMDS_MeshNode* n=0 ) const; bool Add( const vector< TGeomID >& fIDs, const SMDS_MeshNode* n=NULL ) const;
TGeomID HasCommonFace( const B_IntersectPoint * other, TGeomID avoidFace=-1 ) const; TGeomID HasCommonFace( const B_IntersectPoint * other, TGeomID avoidFace=-1 ) const;
size_t GetCommonFaces( const B_IntersectPoint * other, TGeomID * commonFaces ) const; size_t GetCommonFaces( const B_IntersectPoint * other, TGeomID * commonFaces ) const;
bool IsOnFace( TGeomID faceID ) const; bool IsOnFace( TGeomID faceID ) const;
@ -749,6 +754,7 @@ namespace
} }
void Add( const E_IntersectPoint* ip ) void Add( const E_IntersectPoint* ip )
{ {
const std::lock_guard<std::mutex> lock(_eMutex);
// Possible cases before Add(ip): // Possible cases before Add(ip):
/// 1) _node != 0 --> _Node at hex corner ( _intPoint == 0 || _intPoint._node == 0 ) /// 1) _node != 0 --> _Node at hex corner ( _intPoint == 0 || _intPoint._node == 0 )
/// 2) _node == 0 && _intPoint._node != 0 --> link intersected by FACE /// 2) _node == 0 && _intPoint._node != 0 --> link intersected by FACE
@ -1306,6 +1312,7 @@ namespace
bool B_IntersectPoint::Add( const vector< TGeomID >& fIDs, bool B_IntersectPoint::Add( const vector< TGeomID >& fIDs,
const SMDS_MeshNode* n) const const SMDS_MeshNode* n) const
{ {
const std::lock_guard<std::mutex> lock(_bMutex);
size_t prevNbF = _faceIDs.size(); size_t prevNbF = _faceIDs.size();
if ( _faceIDs.empty() ) if ( _faceIDs.empty() )
@ -1318,7 +1325,7 @@ namespace
if ( it == _faceIDs.end() ) if ( it == _faceIDs.end() )
_faceIDs.push_back( fIDs[i] ); _faceIDs.push_back( fIDs[i] );
} }
if ( !_node ) if ( !_node && n != NULL )
_node = n; _node = n;
return prevNbF < _faceIDs.size(); return prevNbF < _faceIDs.size();
@ -3618,6 +3625,35 @@ namespace
return !_volumeDefs._nodes.empty(); return !_volumeDefs._nodes.empty();
} }
template<typename Type>
void computeHexa(Type& hex)
{
if ( hex )
hex->computeElements();
}
// Implement parallel computation of Hexa with c++ thread implementation
template<typename Iterator, class Function>
void parallel_for(const Iterator& first, const Iterator& last, Function&& f, const int nthreads = 1)
{
const unsigned int group = ((last-first))/std::abs(nthreads);
std::vector<std::thread> threads;
threads.reserve(nthreads);
Iterator it = first;
for (; it < last-group; it += group) {
// to create a thread
// Pass iterators by value and the function by reference!
auto lambda = [=,&f](){ std::for_each(it, std::min(it+group, last), f);};
// stack the threads
threads.push_back( std::thread( lambda ) );
}
std::for_each(it, last, f); // last steps while we wait for other threads
std::for_each(threads.begin(), threads.end(), [](std::thread& x){x.join();});
}
//================================================================================ //================================================================================
/*! /*!
* \brief Create elements in the mesh * \brief Create elements in the mesh
@ -3731,9 +3767,9 @@ namespace
// compute definitions of volumes resulted from hexadron intersection // compute definitions of volumes resulted from hexadron intersection
#ifdef WITH_TBB #ifdef WITH_TBB
tbb::parallel_for ( tbb::blocked_range<size_t>( 0, intHexa.size() ), auto numOfThreads = std::thread::hardware_concurrency();
ParallelHexahedron( intHexa ), numOfThreads = (numOfThreads != 0) ? numOfThreads : 1;
tbb::simple_partitioner()); // computeElements() is called here parallel_for(intHexa.begin(), intHexa.end(), computeHexa<Hexahedron*>, numOfThreads );
#else #else
for ( size_t i = 0; i < intHexa.size(); ++i ) for ( size_t i = 0; i < intHexa.size(); ++i )
if ( Hexahedron * hex = intHexa[ i ] ) if ( Hexahedron * hex = intHexa[ i ] )