- imbastimento del multiThread per il calcolo del tree.
This commit is contained in:
@@ -29,9 +29,18 @@
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <execution>
|
||||
#include <queue>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
atomic<int> CellCounter( 0) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Tree::Tree( void)
|
||||
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
|
||||
@@ -255,7 +264,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
for ( int i = 1 ; i < nSplit ; ++i) {
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
double dSplit = bSplitInHalf ? i * SBZ_TREG_COEFF / 2 : i * SBZ_TREG_COEFF ;
|
||||
if ( Split( nId, dSplit)) {
|
||||
if ( Split( nId, dSplit, m_mTree)) {
|
||||
//++ nId ;
|
||||
//++ nId ;
|
||||
nId = m_mTree[nId].m_nChild2 ;
|
||||
@@ -274,7 +283,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
for ( int j = nSplit ; j > 0 ; --j) {
|
||||
m_mTree[nId].SetSplitDirVert( false) ;
|
||||
double dSplit = bSplitInHalf ? j * SBZ_TREG_COEFF / 2 : j * SBZ_TREG_COEFF ;
|
||||
if ( Split( nId, dSplit))
|
||||
if ( Split( nId, dSplit, m_mTree))
|
||||
nId = m_mTree[nId].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
@@ -295,7 +304,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
m_bClosedV = true ;
|
||||
}
|
||||
m_mTree[-1].SetSplitDirVert( false) ;
|
||||
Split( -1) ;
|
||||
Split( -1, m_mTree) ;
|
||||
}
|
||||
////////
|
||||
|
||||
@@ -316,9 +325,9 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
m_vbPole[3] = bPole1 ;
|
||||
if ( bPole0 && bPole1 && int( m_mTree.size() == 3)) {
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
Split( 0, m_mTree) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
Split( 1, m_mTree) ;
|
||||
}
|
||||
}
|
||||
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
|
||||
@@ -332,7 +341,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
m_bClosedU = true ;
|
||||
}
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
Split( -1, m_mTree) ;
|
||||
}
|
||||
////////
|
||||
|
||||
@@ -352,9 +361,9 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
m_vbPole[2] = bPole0 ;
|
||||
if ( bPole0 && bPole1 && int( m_mTree.size()) == 3) {
|
||||
m_mTree[0].SetSplitDirVert( false) ;
|
||||
Split( 0) ;
|
||||
Split( 0, m_mTree) ;
|
||||
m_mTree[1].SetSplitDirVert( false) ;
|
||||
Split( 1) ;
|
||||
Split( 1, m_mTree) ;
|
||||
}
|
||||
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
|
||||
if ( int( m_mTree.size() == 3) && ! m_mTree.at(-1).IsSplitVert()) {
|
||||
@@ -363,9 +372,9 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
m_mTree[1].m_nRight = -1 ;
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
Split( 0, m_mTree) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
Split( 1, m_mTree) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,9 +498,9 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::Split( int nId, double dSplitValue)
|
||||
Tree::Split( int nId, double dSplitValue, unordered_map<int, Cell>& mBranch)
|
||||
{
|
||||
Cell& cToSplit = m_mTree.at(nId) ;
|
||||
Cell& cToSplit = mBranch.at(nId) ;
|
||||
// controllo che lo split non venga fatto sul lato della cella
|
||||
if ( ( cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + EPS_SMALL &&
|
||||
dSplitValue < cToSplit.GetTopRight().x - EPS_SMALL) ||
|
||||
@@ -502,11 +511,10 @@ Tree::Split( int nId, double dSplitValue)
|
||||
Cell cChild1, cChild2 ;
|
||||
cChild1.m_nDepth = cToSplit.m_nDepth + 1 ;
|
||||
cChild2.m_nDepth = cToSplit.m_nDepth + 1 ;
|
||||
int nNodes = (int) m_mTree.size() ;
|
||||
cChild1.m_nId = nNodes - 1 ;
|
||||
cToSplit.m_nChild1 = nNodes - 1 ;
|
||||
cChild2.m_nId = nNodes ;
|
||||
cToSplit.m_nChild2 = nNodes ;
|
||||
cChild1.m_nId = CellCounter.fetch_add( 1) ;
|
||||
cToSplit.m_nChild1 = cChild1.m_nId ;
|
||||
cChild2.m_nId = CellCounter.fetch_add( 1) ;
|
||||
cToSplit.m_nChild2 = cChild2.m_nId ;
|
||||
Point3d ptVert1, ptVert2 ;
|
||||
if ( ! cToSplit.IsSplitVert()) {
|
||||
// la cella figlio 1 è quella sopra
|
||||
@@ -553,8 +561,8 @@ Tree::Split( int nId, double dSplitValue)
|
||||
cChild1.SetParent( nId) ;
|
||||
cChild2.SetParent( nId) ;
|
||||
// inserisco nell'albero
|
||||
m_mTree.insert( pair<int, Cell>( nNodes - 1, cChild1)) ;
|
||||
m_mTree.insert( pair<int, Cell>( nNodes, cChild2)) ;
|
||||
mBranch.insert( pair<int, Cell>( cChild1.m_nId, cChild1)) ;
|
||||
mBranch.insert( pair<int, Cell>( cChild2.m_nId, cChild2)) ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
@@ -562,15 +570,15 @@ Tree::Split( int nId, double dSplitValue)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::Split( int nId)
|
||||
Tree::Split( int nId, unordered_map<int, Cell>& mBranch)
|
||||
{
|
||||
double dValue ;
|
||||
Cell& cCell = m_mTree.at(nId) ;
|
||||
Cell& cCell = mBranch.at(nId) ;
|
||||
if ( cCell.IsSplitVert())
|
||||
dValue = ( cCell.GetBottomLeft().x + cCell.GetTopRight().x) / 2 ;
|
||||
else
|
||||
dValue = ( cCell.GetBottomLeft().y + cCell.GetTopRight().y) / 2 ;
|
||||
return Split( nId, dValue) ;
|
||||
return Split( nId, dValue, mBranch) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -583,25 +591,25 @@ Tree::BuildTree_test( double dLinTol, double dSideMin, double dSideMax)
|
||||
|
||||
//celle 0,1
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
Split( -1, m_mTree) ;
|
||||
//celle 2,3
|
||||
m_mTree[0].SetSplitDirVert( false) ;
|
||||
Split( 0) ;
|
||||
Split( 0, m_mTree) ;
|
||||
//celle 4,5
|
||||
m_mTree[2].SetSplitDirVert( false) ;
|
||||
Split( 2) ;
|
||||
Split( 2, m_mTree) ;
|
||||
//celle 6,7
|
||||
m_mTree[3].SetSplitDirVert( true) ;
|
||||
Split( 3) ;
|
||||
Split( 3, m_mTree) ;
|
||||
//celle 8,9
|
||||
m_mTree[1].SetSplitDirVert( false) ;
|
||||
Split( 1) ;
|
||||
Split( 1, m_mTree) ;
|
||||
//celle 10,11
|
||||
m_mTree[8].SetSplitDirVert( true) ;
|
||||
Split( 8) ;
|
||||
Split( 8, m_mTree) ;
|
||||
//celle 12,13
|
||||
m_mTree[9].SetSplitDirVert( false) ;
|
||||
Split( 9) ;
|
||||
Split( 9, m_mTree) ;
|
||||
m_vnLeaves.push_back( 4) ;
|
||||
//m_vnLeaves.push_back( 5) ;
|
||||
m_vnLeaves.push_back( 6) ;
|
||||
@@ -614,22 +622,22 @@ Tree::BuildTree_test( double dLinTol, double dSideMin, double dSideMax)
|
||||
// aggiunta di split
|
||||
//celle 14,15
|
||||
m_mTree[5].SetSplitDirVert( true) ;
|
||||
Split( 5) ;
|
||||
Split( 5, m_mTree) ;
|
||||
m_vnLeaves.push_back( 14) ;
|
||||
m_vnLeaves.push_back( 15) ;
|
||||
//celle 16,17
|
||||
m_mTree[7].SetSplitDirVert( false) ;
|
||||
Split( 7) ;
|
||||
Split( 7, m_mTree) ;
|
||||
m_vnLeaves.push_back( 16) ;
|
||||
m_vnLeaves.push_back( 17) ;
|
||||
//celle 18,19
|
||||
m_mTree[12].SetSplitDirVert( true) ;
|
||||
Split( 12) ;
|
||||
Split( 12, m_mTree) ;
|
||||
m_vnLeaves.push_back( 18) ;
|
||||
m_vnLeaves.push_back( 19) ;
|
||||
//celle 20,21
|
||||
m_mTree[10].SetSplitDirVert( false) ;
|
||||
Split( 10) ;
|
||||
Split( 10, m_mTree) ;
|
||||
m_vnLeaves.push_back( 20) ;
|
||||
m_vnLeaves.push_back( 21) ;
|
||||
// riempio anche la lista dei parent delle celle
|
||||
@@ -638,16 +646,115 @@ Tree::BuildTree_test( double dLinTol, double dSideMin, double dSideMax)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::BranchManager( queue<function<void()>>& tasks, condition_variable& cv, bool& done)
|
||||
{
|
||||
while (true) {
|
||||
function<void()> task ;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mapMutex);
|
||||
cv.wait(lock, [&tasks, &done]() { return !tasks.empty() || done; });
|
||||
|
||||
if (tasks.empty() && done) {
|
||||
return;
|
||||
}
|
||||
task = move(tasks.front());
|
||||
tasks.pop();
|
||||
}
|
||||
|
||||
task(); // Execute the task
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
{
|
||||
// lancio in parallelo vari thread in modo da calcolare separatamente i branch da ogni foglia attuale
|
||||
int nThreadMax = ( thread::hardware_concurrency()) / 2 ;
|
||||
int nStartingLeaves = m_vnLeaves.size() ;
|
||||
condition_variable cv ;
|
||||
vector<unordered_map<int, Cell>> vBranches( nStartingLeaves) ;
|
||||
// ad ogni ramo, metto come cella di partenza una foglia
|
||||
for ( int i = 0 ; i < nStartingLeaves ; ++i) {
|
||||
Cell cLeaf = m_mTree.at( i) ;
|
||||
vBranches[i].insert( pair<int,Cell>( i, cLeaf)) ;
|
||||
}
|
||||
|
||||
queue<function<void()>> tasks;
|
||||
// Add tasks to the queue
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
for (int i = 0; i < nStartingLeaves; ++i) {
|
||||
tasks.emplace([this]() {});
|
||||
}
|
||||
}
|
||||
|
||||
// Notify threads that tasks are available
|
||||
cv.notify_all();
|
||||
|
||||
// Mark work as done and notify all threads to exit
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
done = true;
|
||||
}
|
||||
cv.notify_all();
|
||||
|
||||
// Wait for all threads to finish
|
||||
for (auto& t : threads) {
|
||||
t.join();
|
||||
}
|
||||
|
||||
|
||||
vector<vector<pair<int, Cell>>> vectorBranches( nStartingLeaves);
|
||||
|
||||
// Step 1: Convert each map to a vector in parallel
|
||||
for_each(execution::par, vectorBranches.begin(), vectorBranches.end(),
|
||||
[&](auto& map) {
|
||||
size_t index = &map - &vectorBranches[0]; // Get the index of the current map
|
||||
vectorBranches[index].assign( make_move_iterator(map.begin()),
|
||||
make_move_iterator(map.end()));
|
||||
});
|
||||
|
||||
// Step 2: Precompute total size and allocate final vector
|
||||
size_t totalSize = accumulate(vectorBranches.begin(), vectorBranches.end(), 0,
|
||||
[](size_t sum, const vector<pair<int, Cell>>& v) {
|
||||
return sum + v.size();
|
||||
}) ;
|
||||
|
||||
vector<pair<int, Cell>> mergedVector( totalSize) ;
|
||||
|
||||
// Step 3: Assign thread-specific ranges and move elements in parallel
|
||||
vector<size_t> offsets( nStartingLeaves + 1, 0) ;
|
||||
for (size_t i = 0; i < nStartingLeaves; ++i)
|
||||
offsets[i + 1] = offsets[i] + vectorBranches[i].size() ;
|
||||
|
||||
for_each( execution::par, vectorBranches.begin(), vectorBranches.end(),
|
||||
[&]( auto& vec) {
|
||||
size_t index = &vec - &vectorBranches[0];
|
||||
move( vec.begin(), vec.end(), mergedVector.begin() + offsets[index]) ;
|
||||
});
|
||||
|
||||
// Step 4: Construct final unordered_map in one bulk step
|
||||
//unordered_map<int, Cell> finalMap( mergedVector.begin(), mergedVector.end()) ;
|
||||
Cell cRoot = m_mTree.at( -1) ;
|
||||
m_mTree.clear() ;
|
||||
m_mTree.insert( pair<int, Cell>(cRoot.m_nId, cRoot)) ;
|
||||
m_mTree.insert( mergedVector.begin(), mergedVector.end()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::BuildBranch( double dLinTol, double dSideMin, double dSideMax, Cell* cBranchRoot, unordered_map<int, Cell>& mBranch)
|
||||
{
|
||||
// suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
|
||||
int nCToSplit = -1 ;
|
||||
Cell* pcToSplit = &m_mTree[nCToSplit] ;
|
||||
int nCToSplit = cBranchRoot->m_nId ;
|
||||
int nBranchRoot = cBranchRoot->m_nId ;
|
||||
Cell* pcToSplit = cBranchRoot ;
|
||||
bool bIsPlanar = m_pSrfBz->IsPlanar() ;
|
||||
if ( ! m_bBilinear) {
|
||||
while ( nCToSplit != -2 && pcToSplit->IsProcessed() == false) {
|
||||
while ( pcToSplit->IsProcessed() == false) {
|
||||
// controllo che la cella non sia già stata preliminarmente splittata
|
||||
if ( pcToSplit->IsLeaf()) {
|
||||
// calcolo in quale direzione ho più curvatura
|
||||
@@ -906,7 +1013,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
if ( bSplit || dSideMaxVal > dSideMax) {
|
||||
pcToSplit->SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
Split( nCToSplit, mBranch) ;
|
||||
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
@@ -919,15 +1026,17 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = pcToSplit->m_nParent ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
if ( nCToSplit == -2)
|
||||
if ( nCToSplit == nBranchRoot)
|
||||
return true ;
|
||||
if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed())
|
||||
pcToSplit->SetProcessed() ;
|
||||
while ( m_mTree[pcToSplit->m_nChild2].IsProcessed()) {
|
||||
if ( pcToSplit->m_nParent != -2) {
|
||||
if ( pcToSplit->m_nParent != nBranchRoot) {
|
||||
nCToSplit = pcToSplit->m_nParent ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
}
|
||||
else
|
||||
return true ;
|
||||
if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed())
|
||||
pcToSplit->SetProcessed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[pcToSplit->m_nChild2].IsProcessed())
|
||||
@@ -1013,7 +1122,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) {
|
||||
pcToSplit->SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
Split( nCToSplit, mBranch) ;
|
||||
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
|
||||
Reference in New Issue
Block a user