From 5c456a60f04e879750d3eead07c4f07652732aaf Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 8 Dec 2017 17:19:47 +0100 Subject: [PATCH] made DynamicCurve balance levelwise optional --- src/blockforest/loadbalancing/DynamicCurve.h | 91 ++++++++++++-------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/src/blockforest/loadbalancing/DynamicCurve.h b/src/blockforest/loadbalancing/DynamicCurve.h index 3cb88476c..14a08f559 100644 --- a/src/blockforest/loadbalancing/DynamicCurve.h +++ b/src/blockforest/loadbalancing/DynamicCurve.h @@ -22,6 +22,7 @@ #pragma once #include "NoPhantomData.h" +#include "blockforest/BlockForest.h" #include "blockforest/HilbertCurveConstruction.h" #include "blockforest/PhantomBlockForest.h" @@ -88,9 +89,14 @@ struct Node } // namespace internal - +/** + * This class implements Hilber and Morton space filling curves for load balancing. + * + * All algorithms are implemented to work levelwise. Load balancing with levels ignored is possible + * by specifying levelwise = false in the constructor. +**/ template< typename PhantomData_T > -class DynamicLevelwiseCurveBalance +class DynamicCurveBalance { public: @@ -99,8 +105,8 @@ public: typedef uint16_t idx_t; // limits the maximum number of blocks per process to 65536 typedef internal::Node< pid_t, idx_t > Node; - DynamicLevelwiseCurveBalance( const bool hilbert = true, const bool allGather = true ) : - hilbert_( hilbert ), allGather_( allGather ) + DynamicCurveBalance( const bool hilbert = true, const bool allGather = true, const bool levelwise = true ) : + hilbert_( hilbert ), allGather_( allGather ), levelwise_(levelwise) {} bool operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, @@ -180,12 +186,17 @@ private: bool hilbert_; bool allGather_; + /// All gets for levels are wrapped like + /// \code levelwise_ ? getCorrectLevel() : 0 + /// + /// This allows to use the same algorithm for levelwise balancing as well as for balancing without levels. + bool levelwise_; }; template< typename PhantomData_T > -bool DynamicLevelwiseCurveBalance< PhantomData_T >::operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, +bool DynamicCurveBalance< PhantomData_T >::operator()( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest, const uint_t ) const { @@ -214,7 +225,7 @@ bool DynamicLevelwiseCurveBalance< PhantomData_T >::operator()( std::vector< std template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherWeighted( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, +void DynamicCurveBalance< PhantomData_T >::allGatherWeighted( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest ) const { @@ -241,7 +252,8 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherWeighted( std::vect recvBuffer >> allBlocks[p]; recvBuffer.reset(); - std::vector< std::vector< std::pair< pid_t, idx_t > > > blocksPerLevel( phantomForest.getNumberOfLevels() ); // for every level one vector of pair(source process ID, index in 'allBlocks') + const uint_t numLevels = levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1); + std::vector< std::vector< std::pair< pid_t, idx_t > > > blocksPerLevel( numLevels ); // for every level one vector of pair(source process ID, index in 'allBlocks') if( hilbert_ ) hilbertOrderWeighted( allBlocks, blocksPerLevel, phantomForest ); @@ -259,7 +271,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherWeighted( std::vect template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherNoWeight( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, +void DynamicCurveBalance< PhantomData_T >::allGatherNoWeight( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest ) const { @@ -283,7 +295,8 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherNoWeight( std::vect recvBuffer >> allBlocks[p]; recvBuffer.reset(); - std::vector< std::vector< std::pair< pid_t, idx_t > > > blocksPerLevel( phantomForest.getNumberOfLevels() ); // for every level one vector of pair(source process ID, index in 'allBlocks') + const uint_t numLevels = levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1); + std::vector< std::vector< std::pair< pid_t, idx_t > > > blocksPerLevel( numLevels ); // for every level one vector of pair(source process ID, index in 'allBlocks') if( hilbert_ ) hilbertOrderNoWeight( allBlocks, blocksPerLevel, phantomForest ); @@ -301,7 +314,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::allGatherNoWeight( std::vect template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::masterWeighted( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, +void DynamicCurveBalance< PhantomData_T >::masterWeighted( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest ) const { @@ -352,7 +365,8 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterWeighted( std::vector< WALBERLA_ASSERT( allBlocks[0].empty() ); allBlocks[0] = localBlocks; - blocksPerLevel.resize( phantomForest.getNumberOfLevels() ); + const uint_t numLevels = levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1); + blocksPerLevel.resize( numLevels ); if( hilbert_ ) hilbertOrderWeighted( allBlocks, blocksPerLevel, phantomForest ); @@ -377,7 +391,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterWeighted( std::vector< template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::masterNoWeight( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, +void DynamicCurveBalance< PhantomData_T >::masterNoWeight( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom, const PhantomBlockForest & phantomForest ) const { @@ -425,7 +439,8 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterNoWeight( std::vector< WALBERLA_ASSERT( allBlocks[0].empty() ); allBlocks[0] = localBlocks; - blocksPerLevel.resize( phantomForest.getNumberOfLevels() ); + const uint_t numLevels = levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1); + blocksPerLevel.resize( numLevels ); if( hilbert_ ) hilbertOrderNoWeight( allBlocks, blocksPerLevel, phantomForest ); @@ -450,9 +465,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterNoWeight( std::vector< template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::hilbertOrderWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, - const PhantomBlockForest & phantomForest ) const + const PhantomBlockForest & phantomForest) const { // construct forest of octrees @@ -519,8 +534,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderWeighted( const else { auto & index = node->index_; - WALBERLA_ASSERT_LESS( blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ].first ), phantomForest.getNumberOfLevels() ); - blocksPerLevel[ blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ].first ) ].push_back( index ); + const uint_t level = levelwise_ ? blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ].first ) : uint_t(0); + WALBERLA_ASSERT_LESS( level, levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1) ); + blocksPerLevel[ level ].push_back( index ); } } } @@ -539,9 +555,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderWeighted( const template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::hilbertOrderNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, - const PhantomBlockForest & phantomForest ) const + const PhantomBlockForest & phantomForest) const { // construct forest of octrees @@ -608,8 +624,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderNoWeight( const else { auto & index = node->index_; - WALBERLA_ASSERT_LESS( blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ] ), phantomForest.getNumberOfLevels() ); - blocksPerLevel[ blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ] ) ].push_back( index ); + const uint_t level = levelwise_ ? blockforest.getLevelFromBlockId( allBlocks[ uint_c(index.first) ][ index.second ] ) : uint_t(0); + WALBERLA_ASSERT_LESS( level , levelwise_ ? phantomForest.getNumberOfLevels() : uint_t(1) ); + blocksPerLevel[ level ].push_back( index ); } } } @@ -628,7 +645,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::hilbertOrderNoWeight( const template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::addBlockToForest( std::vector< shared_ptr< Node > > & forest, +void DynamicCurveBalance< PhantomData_T >::addBlockToForest( std::vector< shared_ptr< Node > > & forest, const std::pair< pid_t, idx_t > & index, BlockID & id, const uint_t level ) const { std::stack< uint_t > path; @@ -681,9 +698,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::addBlockToForest( std::vecto template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::mortonOrderWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, - const PhantomBlockForest & phantomForest ) const + const PhantomBlockForest & phantomForest) const { const uint_t processes = uint_c( mpi::MPIManager::instance()->numProcesses() ); @@ -691,8 +708,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderWeighted( const s { for( uint_t i = uint_t(0); i != allBlocks[p].size(); ++i ) { - WALBERLA_ASSERT_LESS( phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i].first ), blocksPerLevel.size() ); - blocksPerLevel[ phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i].first ) ].push_back( std::make_pair( pid_c(p), idx_c(i) ) ); + uint_t level = levelwise_ ? phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i].first ) : uint_t(0); + WALBERLA_ASSERT_LESS( level, blocksPerLevel.size() ); + blocksPerLevel[ level ].push_back( std::make_pair( pid_c(p), idx_c(i) ) ); } } @@ -710,9 +728,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderWeighted( const s template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::mortonOrderNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, - const PhantomBlockForest & phantomForest ) const + const PhantomBlockForest & phantomForest) const { const uint_t processes = uint_c( mpi::MPIManager::instance()->numProcesses() ); @@ -720,8 +738,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderNoWeight( const s { for( uint_t i = uint_t(0); i != allBlocks[p].size(); ++i ) { - WALBERLA_ASSERT_LESS( phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i] ), blocksPerLevel.size() ); - blocksPerLevel[ phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i] ) ].push_back( std::make_pair( pid_c(p), idx_c(i) ) ); + uint_t level = levelwise_ ? phantomForest.getBlockForest().getLevelFromBlockId( allBlocks[p][i] ) : uint_t(0); + WALBERLA_ASSERT_LESS( level, blocksPerLevel.size() ); + blocksPerLevel[ level ].push_back( std::make_pair( pid_c(p), idx_c(i) ) ); } } @@ -739,7 +758,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::mortonOrderNoWeight( const s template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::balanceWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::balanceWeighted( const std::vector< std::vector< std::pair< BlockID, typename PhantomData_T::weight_t > > > & allBlocks, const std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, std::vector< std::vector<pid_t> > & targets, std::vector< std::set<pid_t> > & sender ) const @@ -790,7 +809,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::balanceWeighted( const std:: template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::balanceNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, +void DynamicCurveBalance< PhantomData_T >::balanceNoWeight( const std::vector< std::vector< BlockID > > & allBlocks, const std::vector< std::vector< std::pair< pid_t, idx_t > > > & blocksPerLevel, std::vector< std::vector<pid_t> > & targets, std::vector< std::set<pid_t> > & sender ) const @@ -825,7 +844,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::balanceNoWeight( const std:: template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::masterEnd( std::vector< std::vector<pid_t> > & targets, +void DynamicCurveBalance< PhantomData_T >::masterEnd( std::vector< std::vector<pid_t> > & targets, std::vector< std::set<pid_t> > & sender, std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom ) const @@ -893,7 +912,7 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterEnd( std::vector< std: template< typename PhantomData_T > -void DynamicLevelwiseCurveBalance< PhantomData_T >::finalAssignment( const uint_t index, const std::vector< std::vector<pid_t> > & targets, +void DynamicCurveBalance< PhantomData_T >::finalAssignment( const uint_t index, const std::vector< std::vector<pid_t> > & targets, const std::vector< std::set<pid_t> > & sender, std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, std::set< uint_t > & processesToRecvFrom ) const @@ -907,7 +926,9 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::finalAssignment( const uint_ processesToRecvFrom.insert( uint_c(*s) ) ; } - +///This class is deprecated use DynamicCurveBalance instead. +template< typename PhantomData_T > +using DynamicLevelwiseCurveBalance = DynamicCurveBalance<PhantomData_T> ; } // namespace blockforest } // namespace walberla -- GitLab