From dfec7c3a4c3d43e8b3b48c11b16fb2ecc29a97e0 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 1 Apr 2025 15:14:43 +0200 Subject: [PATCH] EgtGeomKernel: - aggiunto mutex per l'accesso a m_vnLeaves - creazione in parallelo della mappa finale m_mTree. --- Tree.cpp | 117 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index e5efc73..4c97432 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -106,7 +106,7 @@ Tree::AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) return true ; } -mutex map3D ; +mutex map3DMutex ; //---------------------------------------------------------------------------- bool @@ -116,18 +116,18 @@ Tree::GetPoint( double dU, double dV, Point3d& pt) const bool bOk = true ; bool bCalculated = false ; { - lock_guard lock( map3D) ; + lock_guard lock( map3DMutex) ; bCalculated = m_mPt3d.find( key) != m_mPt3d.end() ; } if ( ! bCalculated) { bOk = bOk && m_pSrfBz->GetPoint( dU / SBZ_TREG_COEFF, dV / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt) ; { - lock_guard lock( map3D) ; + lock_guard lock( map3DMutex) ; m_mPt3d[key] = pt ; } } { - lock_guard lock( map3D) ; + lock_guard lock( map3DMutex) ; pt = m_mPt3d[key] ; } return bOk ; @@ -140,11 +140,11 @@ Tree::SavePoint( double dU, double dV, Point3d& pt) pair key (static_cast(dU * pow(2,15)), static_cast(dV * pow(2,15))) ; bool bCalculated = true ; { - lock_guard lock( map3D) ; + lock_guard lock( map3DMutex) ; bCalculated = m_mPt3d.find( key) != m_mPt3d.end() ; } if ( ! bCalculated){ - lock_guard lock( map3D) ; + lock_guard lock( map3DMutex) ; m_mPt3d[key] = pt ; } return true ; @@ -741,56 +741,59 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) for ( auto& t : workers) t.join() ; - // debug - for ( int i = 0 ; i < nStartingLeaves ; ++i) - m_mTree.erase( vFirstCells[i]) ; - for ( int i = 0 ; i < nStartingLeaves ; ++i) - m_mTree.insert( vBranches[i].begin(), vBranches[i].end()) ; - - return true ; - // debug - - - //vector>> vectorBranches( nStartingLeaves); - - //// Step 1: Convert each map to a vector in parallel - //for_each(execution::par, vBranches.begin(), vBranches.end(), - // [&](auto& map) { - // size_t index = &map - &vBranches[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>& v) { - // return sum + v.size(); - // }) ; - - //vector> mergedVector( totalSize) ; - - //// Step 3: Assign thread-specific ranges and move elements in parallel - //vector offsets( nStartingLeaves + 1, 0) ; - //for (int 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 finalMap( mergedVector.begin(), mergedVector.end()) ; - //Cell cRoot = m_mTree.at( -1) ; - //m_mTree.clear() ; - //unordered_map mContainer( mergedVector.begin(), mergedVector.end()) ; - //m_mTree = std::move( mContainer) ; - //m_mTree.insert( pair( cRoot.m_nId, cRoot)) ; + //// debug + //for ( int i = 0 ; i < nStartingLeaves ; ++i) + // m_mTree.erase( vFirstCells[i]) ; + //for ( int i = 0 ; i < nStartingLeaves ; ++i) + // m_mTree.insert( vBranches[i].begin(), vBranches[i].end()) ; //return true ; + //// debug + + vector>> vectorBranches( nStartingLeaves); + + // Step 1: Convert each map to a vector in parallel + for_each(execution::par, vBranches.begin(), vBranches.end(), + [&](auto& map) { + size_t index = &map - &vBranches[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>& v) { + return sum + v.size(); + }) ; + + vector> mergedVector( totalSize) ; + + // Step 3: Assign thread-specific ranges and move elements in parallel + vector offsets( nStartingLeaves + 1, 0) ; + for (int 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 BranchesStart( m_mTree.begin(), m_mTree.end()) ; + m_mTree.clear() ; + unordered_map mContainer( mergedVector.begin(), mergedVector.end()) ; + m_mTree = std::move( mContainer) ; + + for ( int i = 0 ; i < nStartingLeaves ; ++i) + BranchesStart.erase( vFirstCells[i]) ; + m_mTree.insert( BranchesStart.begin(), BranchesStart.end()) ; + + return true ; } +mutex leavesMutex ; + //---------------------------------------------------------------------------- bool Tree::BuildBranch( int nFirstCell, unordered_map& mBranch, double dLinTol, double dSideMin, double dSideMax) @@ -1068,7 +1071,10 @@ Tree::BuildBranch( int nFirstCell, unordered_map& mBranch, double dLi } else { // sono arrivato ad una cella Leaf, quindi salvo la cella - m_vnLeaves.push_back( nCToSplit) ; + { + lock_guard lock( leavesMutex) ; + m_vnLeaves.push_back( nCToSplit) ; + } pcToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare nCToSplit = pcToSplit->m_nParent ; @@ -1177,7 +1183,10 @@ Tree::BuildBranch( int nFirstCell, unordered_map& mBranch, double dLi } else { // sono arrivato ad una cella Leaf, quindi salvo la cella - m_vnLeaves.push_back( nCToSplit) ; + { + lock_guard lock( leavesMutex) ; + m_vnLeaves.push_back( nCToSplit) ; + } pcToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare nCToSplit = pcToSplit->m_nParent ;