From 1344ba5e853cdfff3b26ef5e4942ddbafa36dbb7 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 28 Sep 2023 13:56:25 +0200 Subject: [PATCH 01/18] reorder and print parameters for unconstrained --- mt-kahypar/partition/context.cpp | 15 +++++++++++++++ mt-kahypar/partition/context.h | 9 ++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/mt-kahypar/partition/context.cpp b/mt-kahypar/partition/context.cpp index 5af1e05f2..03dd4bfd4 100644 --- a/mt-kahypar/partition/context.cpp +++ b/mt-kahypar/partition/context.cpp @@ -123,8 +123,10 @@ namespace mt_kahypar { str << " Algorithm: " << params.algorithm << std::endl; if ( params.algorithm != LabelPropagationAlgorithm::do_nothing ) { str << " Maximum Iterations: " << params.maximum_iterations << std::endl; + str << " Unconstrained: " << std::boolalpha << params.unconstrained << std::endl; str << " Rebalancing: " << std::boolalpha << params.rebalancing << std::endl; str << " HE Size Activation Threshold: " << std::boolalpha << params.hyperedge_size_activation_threshold << std::endl; + str << " Relative Improvement Threshold: " << params.relative_improvement_threshold << std::endl; } return str; } @@ -144,6 +146,19 @@ namespace mt_kahypar { out << " Release Nodes: " << std::boolalpha << params.release_nodes << std::endl; out << " Time Limit Factor: " << params.time_limit_factor << std::endl; } + if ( params.algorithm == FMAlgorithm::unconstrained_fm ) { + out << " Unconstrained Rounds: " << params.unconstrained_rounds << std::endl; + out << " Threshold Border Node Inclusion: " << params.treshold_border_node_inclusion << std::endl; + out << " Minimum Imbalance Penalty Factor: " << params.imbalance_penalty_min << std::endl; + out << " Maximum Imbalance Penalty Factor: " << params.imbalance_penalty_max << std::endl; + out << " Start Upper Bound for Unc.: " << params.unconstrained_upper_bound << std::endl; + out << " Final Upper Bound for Unc.: " << params.unconstrained_upper_bound_min << std::endl; + out << " Unc. Minimum Improvement Factor: " << params.unconstrained_min_improvement << std::endl; + out << " Activate Unc. Dynamically: " << std::boolalpha << params.activate_unconstrained_dynamically << std::endl; + if ( params.activate_unconstrained_dynamically ) { + out << " Penalty for Activation Test: " << params.penalty_for_activation_test << std::endl; + } + } out << std::flush; return out; } diff --git a/mt-kahypar/partition/context.h b/mt-kahypar/partition/context.h index c6b59f98a..906cc65ed 100644 --- a/mt-kahypar/partition/context.h +++ b/mt-kahypar/partition/context.h @@ -133,9 +133,9 @@ std::ostream & operator<< (std::ostream& str, const CoarseningParameters& params struct LabelPropagationParameters { LabelPropagationAlgorithm algorithm = LabelPropagationAlgorithm::do_nothing; size_t maximum_iterations = 1; + bool unconstrained = false; bool rebalancing = true; bool execute_sequential = false; - bool unconstrained = false; size_t hyperedge_size_activation_threshold = std::numeric_limits::max(); double relative_improvement_threshold = -1.0; }; @@ -159,18 +159,17 @@ struct FMParameters { mutable bool obey_minimal_parallelism = false; bool release_nodes = true; - double treshold_border_node_inclusion = 0.75; - double unconstrained_upper_bound = 0.0; - // unconstrained size_t unconstrained_rounds = 1; + double treshold_border_node_inclusion = 0.75; double imbalance_penalty_min = 0.2; double imbalance_penalty_max = 1.0; + double unconstrained_upper_bound = 0.0; double unconstrained_upper_bound_min = 0.0; + double unconstrained_min_improvement = -1.0; bool activate_unconstrained_dynamically = false; double penalty_for_activation_test = 0.5; - double unconstrained_min_improvement = -1.0; }; std::ostream& operator<<(std::ostream& out, const FMParameters& params); From 853efea7a3d30c9e39bdd0cbe9f554dd69967225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gottesb=C3=BCren?= Date: Mon, 4 Sep 2023 13:34:14 +0200 Subject: [PATCH 02/18] [FM refactoring] remove FM version running on shared partition --- .../partition/refinement/fm/fm_commons.h | 9 +- .../refinement/fm/localized_kway_fm_core.cpp | 191 ++++-------------- .../refinement/fm/localized_kway_fm_core.h | 15 +- 3 files changed, 43 insertions(+), 172 deletions(-) diff --git a/mt-kahypar/partition/refinement/fm/fm_commons.h b/mt-kahypar/partition/refinement/fm/fm_commons.h index 8bdd5c4fc..7d9a68b4b 100644 --- a/mt-kahypar/partition/refinement/fm/fm_commons.h +++ b/mt-kahypar/partition/refinement/fm/fm_commons.h @@ -65,7 +65,7 @@ struct GlobalMoveTracker { } } - MoveID insertMove(Move &m) { + MoveID insertMove(const Move &m) { const MoveID move_id = runningMoveID.fetch_add(1, std::memory_order_relaxed); assert(move_id - firstMoveID < moveOrder.size()); moveOrder[move_id - firstMoveID] = m; @@ -274,10 +274,6 @@ struct FMSharedData { CAtomic finishedTasks; size_t finishedTasksLimit = std::numeric_limits::max(); - // ! Switch to applying moves directly if the use of local delta partitions exceeded a memory limit - bool deltaExceededMemoryConstraints = false; - size_t deltaMemoryLimitPerThread = 0; - bool release_nodes = true; bool perform_moves_global = true; @@ -291,9 +287,6 @@ struct FMSharedData { unconstrained(numNodes) { finishedTasks.store(0, std::memory_order_relaxed); - // 128 * 3/2 GB --> roughly 1.5 GB per thread on our biggest machine - deltaMemoryLimitPerThread = 128UL * (UL(1) << 30) * 3 / ( 2 * std::max(UL(1), numThreads) ); - tbb::parallel_invoke([&] { moveTracker.moveOrder.resize(numNodes); }, [&] { diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp index 149bc21f2..263bfbc39 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp @@ -49,26 +49,13 @@ namespace mt_kahypar { } if (runStats.pushes > 0) { - if (sharedData.deltaExceededMemoryConstraints) { - deltaPhg.dropMemory(); - delta_gain_cache.dropMemory(); - } - - if (context.refinement.fm.perform_moves_global || sharedData.deltaExceededMemoryConstraints) { - if ( phg.hasFixedVertices() ) { - internalFindMoves(phg, fm_strategy); - } else { - internalFindMoves(phg, fm_strategy); - } + deltaPhg.clear(); + deltaPhg.setPartitionedHypergraph(&phg); + delta_gain_cache.clear(); + if ( phg.hasFixedVertices() ) { + internalFindMoves(phg, fm_strategy); } else { - deltaPhg.clear(); - delta_gain_cache.clear(); - deltaPhg.setPartitionedHypergraph(&phg); - if ( phg.hasFixedVertices() ) { - internalFindMoves(phg, fm_strategy); - } else { - internalFindMoves(phg, fm_strategy); - } + internalFindMoves(phg, fm_strategy); } return true; } else { @@ -126,30 +113,12 @@ namespace mt_kahypar { template - template + template void LocalizedKWayFM::internalFindMoves(PartitionedHypergraph& phg, DispatchedFMStrategy& fm_strategy) { StopRule stopRule(phg.initialNumNodes()); Move move; - auto delta_func = [&](const SynchronizedEdgeUpdate& sync_update) { - // Gains of the pins of a hyperedge can only change in the following situations. - if ( GainCache::triggersDeltaGainUpdate(sync_update) ) { - edgesWithGainChanges.push_back(sync_update.he); - } - - if constexpr (use_delta) { - fm_strategy.deltaGainUpdates(deltaPhg, delta_gain_cache, sync_update); - } else { - fm_strategy.deltaGainUpdates(phg, gain_cache, sync_update); - } - }; - - // we can almost make this function take a generic partitioned hypergraph - // we would have to add the success func to the interface of DeltaPhg (and then ignore it there...) - // and do the local rollback outside this function - - size_t bestImprovementIndex = 0; Gain estimatedImprovement = 0; Gain bestImprovement = 0; @@ -159,11 +128,7 @@ namespace mt_kahypar { while (!stopRule.searchShouldStop() && sharedData.finishedTasks.load(std::memory_order_relaxed) < sharedData.finishedTasksLimit) { - if constexpr (use_delta) { - if (!fm_strategy.findNextMove(deltaPhg, delta_gain_cache, move)) break; - } else { - if (!fm_strategy.findNextMove(phg, gain_cache, move)) break; - } + if (!fm_strategy.findNextMove(deltaPhg, delta_gain_cache, move)) break; sharedData.nodeTracker.deactivateNode(move.node, thisSearch); // skip if no target block available @@ -178,37 +143,31 @@ namespace mt_kahypar { if (!expect_improvement && high_deg) { continue; } - // less restrictive option: skip if negative gain (or < -5000 or smth). - // downside: have to flush before improvement or run it through deltaPhg - // probably quite similar since this only really matters in the first few moves where the stop rule - // doesn't signal us to stop yet edgesWithGainChanges.clear(); // clear before move. delta_func feeds nets of moved vertex. MoveID move_id = std::numeric_limits::max(); bool moved = false; const HypernodeWeight allowed_weight = DispatchedFMStrategy::is_unconstrained ? std::numeric_limits::max() : context.partition.max_part_weights[move.to]; - if constexpr (use_delta) { - heaviestPartWeight = heaviestPartAndWeight(deltaPhg, context.partition.k).second; - fromWeight = deltaPhg.partWeight(move.from); - toWeight = deltaPhg.partWeight(move.to); - if (expect_improvement) { - // since we will flush the move sequence, don't bother running it through the deltaPhg - // this is intended to allow moving high deg nodes (blow up hash tables) if they give an improvement. - // The nets affected by a gain cache update are collected when we apply this improvement on the - // global partition (used to expand the localized search and update the gain values). - moved = toWeight + phg.nodeWeight(move.node) <= allowed_weight; - } else { - moved = deltaPhg.changeNodePart(move.node, move.from, move.to, allowed_weight, delta_func); - fm_strategy.applyMove(deltaPhg, delta_gain_cache, move, false); - } + + heaviestPartWeight = heaviestPartAndWeight(deltaPhg, context.partition.k).second; + fromWeight = deltaPhg.partWeight(move.from); + toWeight = deltaPhg.partWeight(move.to); + if (expect_improvement) { + // since we will flush the move sequence, don't bother running it through the deltaPhg + // this is intended to allow moving high deg nodes (blow up hash tables) if they give an improvement. + // The nets affected by a gain cache update are collected when we apply this improvement on the + // global partition (used to expand the localized search and update the gain values). + moved = toWeight + phg.nodeWeight(move.node) <= allowed_weight; } else { - heaviestPartWeight = heaviestPartAndWeight(phg, context.partition.k).second; - fromWeight = phg.partWeight(move.from); - toWeight = phg.partWeight(move.to); - moved = phg.changeNodePart(move.node, move.from, move.to, allowed_weight, - [&] { move_id = sharedData.moveTracker.insertMove(move); }, delta_func); - fm_strategy.applyMove(phg, gain_cache, move, true); + moved = deltaPhg.changeNodePart(move.node, move.from, move.to, allowed_weight, + [&](const SynchronizedEdgeUpdate& sync_update) { + if (GainCache::triggersDeltaGainUpdate(sync_update)) { + edgesWithGainChanges.push_back(sync_update.he); + } + delta_gain_cache.deltaGainUpdate(deltaPhg, sync_update); + }); + fm_strategy.applyMove(deltaPhg, delta_gain_cache, move, false); } if (moved) { @@ -221,17 +180,21 @@ namespace mt_kahypar { && fromWeight == heaviestPartWeight && toWeight + phg.nodeWeight(move.node) < heaviestPartWeight; if (improved_km1 || improved_balance_less_equal_km1) { + // Apply move sequence to global partition + for (size_t i = 0; i < localMoves.size(); ++i) { + const Move& local_move = localMoves[i].first; + phg.changeNodePart( + gain_cache, local_move.node, local_move.from, local_move.to, + std::numeric_limits::max(), + [&] { sharedData.moveTracker.insertMove(local_move); }, + [&](const SynchronizedEdgeUpdate& ) {}); + } + localMoves.clear(); + fm_strategy.flushLocalChanges(); stopRule.reset(); + deltaPhg.clear(); // clear hashtables, save memory :) + delta_gain_cache.clear(); bestImprovement = estimatedImprovement; - bestImprovementIndex = localMoves.size(); - - if constexpr (use_delta) { - applyBestLocalPrefixToSharedPartition(phg, fm_strategy, bestImprovementIndex); - bestImprovementIndex = 0; - localMoves.clear(); - deltaPhg.clear(); // clear hashtables, save memory :) - delta_gain_cache.clear(); - } } // no need to update our PQs if we stop anyways @@ -240,20 +203,8 @@ namespace mt_kahypar { break; } - if constexpr (use_delta) { - acquireOrUpdateNeighbors(deltaPhg, delta_gain_cache, move, fm_strategy); - } else { - acquireOrUpdateNeighbors(phg, gain_cache, move, fm_strategy); - } + acquireOrUpdateNeighbors(deltaPhg, delta_gain_cache, move, fm_strategy); } - - } - - if constexpr (use_delta) { - // in this case there is no improved local prefix to apply (was already applied in the loop) - ASSERT(bestImprovementIndex == 0); - } else { - revertToBestLocalPrefix(phg, fm_strategy, bestImprovementIndex); } fm_strategy.reset(); @@ -262,68 +213,6 @@ namespace mt_kahypar { } - template - template - void LocalizedKWayFM::applyBestLocalPrefixToSharedPartition( - PartitionedHypergraph& phg, - DispatchedFMStrategy& fm_strategy, - const size_t best_index_locally_observed) { - // Note: if this precondition does not hold, the call to fm_strategy.flushLocalChanges() would be incorrect - ASSERT(best_index_locally_observed == localMoves.size()); - - bool is_last_move = false; - - auto delta_gain_func = [&](const SynchronizedEdgeUpdate& sync_update) { - // Gains of the pins of a hyperedge can only change in the following situations. - if ( is_last_move && GainCache::triggersDeltaGainUpdate(sync_update) ) { - // This vector is used by the acquireOrUpdateNeighbor function to expand to neighbors - // or update the gain values of neighbors of the moved node and is cleared afterwards. - // BEWARE. Adding the nets at this stage works, because the vector is cleared before the move, - // and the expansion happens after applyBestLocalPrefixToSharedPartition. - edgesWithGainChanges.push_back(sync_update.he); - } - }; - - // Apply move sequence to original hypergraph - for (size_t i = 0; i < best_index_locally_observed; ++i) { - ASSERT(i < localMoves.size()); - Move& local_move = localMoves[i].first; - MoveID& move_id = localMoves[i].second; - // In a localized FM search, we apply all moves to a thread-local partition (delta_phg) - // using hash tables. Once we find an improvement, we apply the corresponding move - // sequence to the global partition. To save memory (in the hash tables), we do not apply - // the last move that leads to the improvement to the thread-local partition as we reset them after - // an improvement is found, anyways. However, when applying a move on the thread-local partition, - // we collect all nets affected by a gain cache update and expand the search to pins - // contained in these nets. Since, we do not apply last move on the thread-local partition we collect - // these nets here. - is_last_move = (i == best_index_locally_observed - 1); - - phg.changeNodePart( - gain_cache, local_move.node, local_move.from, local_move.to, - std::numeric_limits::max(), - [&] { move_id = sharedData.moveTracker.insertMove(local_move); }, - delta_gain_func); - ASSERT(move_id != std::numeric_limits::max()); - } - fm_strategy.flushLocalChanges(); - } - - template - template - void LocalizedKWayFM::revertToBestLocalPrefix(PartitionedHypergraph& phg, - DispatchedFMStrategy& fm_strategy, - size_t bestGainIndex) { - runStats.local_reverts += localMoves.size() - bestGainIndex; - while (localMoves.size() > bestGainIndex) { - Move& m = sharedData.moveTracker.getMove(localMoves.back().second); - phg.changeNodePart(gain_cache, m.node, m.to, m.from); - fm_strategy.revertMove(phg, gain_cache, m, true); - m.invalidate(); - localMoves.pop_back(); - } - } - template void LocalizedKWayFM::changeNumberOfBlocks(const PartitionID new_k) { deltaPhg.changeNumberOfBlocks(new_k); diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h index d299e5c04..dc6076ad8 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h @@ -88,7 +88,7 @@ class LocalizedKWayFM { FMStats stats; private: - template + template void internalFindMoves(PartitionedHypergraph& phg, DispatchedFMStrategy& fm_strategy); template @@ -96,17 +96,6 @@ class LocalizedKWayFM { void acquireOrUpdateNeighbors(PHG& phg, CACHE& gain_cache, const Move& move, DispatchedFMStrategy& fm_strategy); - // ! Makes moves applied on delta hypergraph visible on the global partitioned hypergraph. - template - void applyBestLocalPrefixToSharedPartition(PartitionedHypergraph& phg, - DispatchedFMStrategy& fm_strategy, - const size_t best_index_locally_observed); - - // ! Rollback to the best improvement found during local search in case we applied moves - // ! directly on the global partitioned hypergraph. - template - void revertToBestLocalPrefix(PartitionedHypergraph& phg, DispatchedFMStrategy& fm_strategy, size_t bestGainIndex); - private: const Context& context; @@ -147,4 +136,4 @@ class LocalizedKWayFM { vec vertexPQs; }; -} \ No newline at end of file +} From 7debc4368237ba8c855b02edbb8e7591d170dd7a Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 28 Sep 2023 12:58:31 +0200 Subject: [PATCH 03/18] [FM refactoring] remove perform_moves_global parameter that is not required anymore --- mt-kahypar/io/command_line_options.cpp | 5 ----- mt-kahypar/io/sql_plottools_serializer.cpp | 1 - mt-kahypar/partition/context.cpp | 5 ----- mt-kahypar/partition/context.h | 1 - mt-kahypar/partition/refinement/fm/fm_commons.h | 1 - .../partition/refinement/fm/multitry_kway_fm.cpp | 2 -- tests/io/context_test.cc.in | 12 ------------ tests/partition/refinement/multitry_fm_test.cc | 1 - 8 files changed, 28 deletions(-) diff --git a/mt-kahypar/io/command_line_options.cpp b/mt-kahypar/io/command_line_options.cpp index 4474c1df2..554d66b95 100644 --- a/mt-kahypar/io/command_line_options.cpp +++ b/mt-kahypar/io/command_line_options.cpp @@ -407,11 +407,6 @@ namespace mt_kahypar { po::value((initial_partitioning ? &context.initial_partitioning.refinement.fm.multitry_rounds : &context.refinement.fm.multitry_rounds))->value_name("")->default_value(10), "Number of FM rounds within one level of the multilevel hierarchy.") - ((initial_partitioning ? "i-r-fm-perform-moves-global" : "r-fm-perform-moves-global"), - po::value((initial_partitioning ? &context.initial_partitioning.refinement.fm.perform_moves_global : - &context.refinement.fm.perform_moves_global))->value_name("")->default_value(false), - "If true, then all moves performed during FM are immediately visible to other searches.\n" - "Otherwise, only move sequences that yield an improvement are applied to the global view of the partition.") ((initial_partitioning ? "i-r-fm-seed-nodes" : "r-fm-seed-nodes"), po::value((initial_partitioning ? &context.initial_partitioning.refinement.fm.num_seed_nodes : &context.refinement.fm.num_seed_nodes))->value_name("")->default_value(25), diff --git a/mt-kahypar/io/sql_plottools_serializer.cpp b/mt-kahypar/io/sql_plottools_serializer.cpp index fe1b2f8d1..7ae725597 100644 --- a/mt-kahypar/io/sql_plottools_serializer.cpp +++ b/mt-kahypar/io/sql_plottools_serializer.cpp @@ -121,7 +121,6 @@ std::string serialize(const PartitionedHypergraph& hypergraph, << " sync_lp_recalculate_gains_on_second_apply=" << context.refinement.deterministic_refinement.recalculate_gains_on_second_apply; oss << " fm_algorithm=" << context.refinement.fm.algorithm << " fm_multitry_rounds=" << context.refinement.fm.multitry_rounds - << " fm_perform_moves_global=" << std::boolalpha << context.refinement.fm.perform_moves_global << " fm_rollback_parallel=" << std::boolalpha << context.refinement.fm.rollback_parallel << " fm_rollback_sensitive_to_num_moves=" << std::boolalpha << context.refinement.fm.iter_moves_on_recalc << " fm_rollback_balance_violation_factor=" << context.refinement.fm.rollback_balance_violation_factor diff --git a/mt-kahypar/partition/context.cpp b/mt-kahypar/partition/context.cpp index 03dd4bfd4..431b00954 100644 --- a/mt-kahypar/partition/context.cpp +++ b/mt-kahypar/partition/context.cpp @@ -136,7 +136,6 @@ namespace mt_kahypar { out << " Algorithm: " << params.algorithm << std::endl; if ( params.algorithm != FMAlgorithm::do_nothing ) { out << " Multitry Rounds: " << params.multitry_rounds << std::endl; - out << " Perform Moves Globally: " << std::boolalpha << params.perform_moves_global << std::endl; out << " Parallel Global Rollbacks: " << std::boolalpha << params.rollback_parallel << std::endl; out << " Rollback Bal. Violation Factor: " << params.rollback_balance_violation_factor << std::endl; out << " Num Seed Nodes: " << params.num_seed_nodes << std::endl; @@ -540,7 +539,6 @@ namespace mt_kahypar { // initial partitioning -> refinement -> fm initial_partitioning.refinement.fm.algorithm = FMAlgorithm::kway_fm; initial_partitioning.refinement.fm.multitry_rounds = 5; - initial_partitioning.refinement.fm.perform_moves_global = false; initial_partitioning.refinement.fm.rollback_parallel = true; initial_partitioning.refinement.fm.rollback_balance_violation_factor = 1; initial_partitioning.refinement.fm.num_seed_nodes = 25; @@ -568,7 +566,6 @@ namespace mt_kahypar { refinement.fm.algorithm = FMAlgorithm::unconstrained_fm; refinement.fm.multitry_rounds = 10; refinement.fm.unconstrained_rounds = 8; - refinement.fm.perform_moves_global = false; refinement.fm.rollback_parallel = true; refinement.fm.rollback_balance_violation_factor = 1.0; refinement.fm.treshold_border_node_inclusion = 0.7; @@ -771,7 +768,6 @@ namespace mt_kahypar { // initial partitioning -> refinement -> fm initial_partitioning.refinement.fm.algorithm = FMAlgorithm::kway_fm; initial_partitioning.refinement.fm.multitry_rounds = 5; - initial_partitioning.refinement.fm.perform_moves_global = false; initial_partitioning.refinement.fm.rollback_parallel = false; initial_partitioning.refinement.fm.rollback_balance_violation_factor = 1; initial_partitioning.refinement.fm.num_seed_nodes = 5; @@ -801,7 +797,6 @@ namespace mt_kahypar { // refinement -> fm refinement.fm.algorithm = FMAlgorithm::kway_fm; refinement.fm.multitry_rounds = 10; - refinement.fm.perform_moves_global = false; refinement.fm.rollback_parallel = false; refinement.fm.rollback_balance_violation_factor = 1.25; refinement.fm.num_seed_nodes = 5; diff --git a/mt-kahypar/partition/context.h b/mt-kahypar/partition/context.h index 906cc65ed..c40813974 100644 --- a/mt-kahypar/partition/context.h +++ b/mt-kahypar/partition/context.h @@ -152,7 +152,6 @@ struct FMParameters { double min_improvement = -1.0; double time_limit_factor = std::numeric_limits::max(); - bool perform_moves_global = false; bool rollback_parallel = true; bool iter_moves_on_recalc = false; bool shuffle = true; diff --git a/mt-kahypar/partition/refinement/fm/fm_commons.h b/mt-kahypar/partition/refinement/fm/fm_commons.h index 7d9a68b4b..ad153760b 100644 --- a/mt-kahypar/partition/refinement/fm/fm_commons.h +++ b/mt-kahypar/partition/refinement/fm/fm_commons.h @@ -275,7 +275,6 @@ struct FMSharedData { size_t finishedTasksLimit = std::numeric_limits::max(); bool release_nodes = true; - bool perform_moves_global = true; FMSharedData(size_t numNodes, size_t numThreads) : numberOfNodes(numNodes), diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp index bd5a95d7d..76658de52 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp @@ -92,7 +92,6 @@ namespace mt_kahypar { size_t consecutive_rounds_with_too_little_improvement = 0; enable_light_fm = false; sharedData.release_nodes = context.refinement.fm.release_nodes; - sharedData.perform_moves_global = context.refinement.fm.perform_moves_global; double current_time_limit = time_limit; tbb::task_group tg; vec initialPartWeights(size_t(context.partition.k)); @@ -200,7 +199,6 @@ namespace mt_kahypar { if ( !enable_light_fm ) { DBG << RED << "Multitry FM reached time limit => switch to Light FM Configuration" << END; sharedData.release_nodes = false; - sharedData.perform_moves_global = true; current_time_limit *= 2; enable_light_fm = true; } else { diff --git a/tests/io/context_test.cc.in b/tests/io/context_test.cc.in index 31890e06c..05db51d63 100644 --- a/tests/io/context_test.cc.in +++ b/tests/io/context_test.cc.in @@ -132,8 +132,6 @@ TEST(AContext, LoadsDefaultPresetCorrectly) { expected.initial_partitioning.refinement.fm.min_improvement); ASSERT_EQ(actual.initial_partitioning.refinement.fm.time_limit_factor, expected.initial_partitioning.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.initial_partitioning.refinement.fm.perform_moves_global, - expected.initial_partitioning.refinement.fm.perform_moves_global); ASSERT_EQ(actual.initial_partitioning.refinement.fm.rollback_parallel, expected.initial_partitioning.refinement.fm.rollback_parallel); ASSERT_EQ(actual.initial_partitioning.refinement.fm.iter_moves_on_recalc, @@ -179,8 +177,6 @@ TEST(AContext, LoadsDefaultPresetCorrectly) { expected.refinement.fm.min_improvement); ASSERT_EQ(actual.refinement.fm.time_limit_factor, expected.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.refinement.fm.perform_moves_global, - expected.refinement.fm.perform_moves_global); ASSERT_EQ(actual.refinement.fm.rollback_parallel, expected.refinement.fm.rollback_parallel); ASSERT_EQ(actual.refinement.fm.iter_moves_on_recalc, @@ -300,8 +296,6 @@ TEST(AContext, LoadsQualityPresetCorrectly) { expected.initial_partitioning.refinement.fm.min_improvement); ASSERT_EQ(actual.initial_partitioning.refinement.fm.time_limit_factor, expected.initial_partitioning.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.initial_partitioning.refinement.fm.perform_moves_global, - expected.initial_partitioning.refinement.fm.perform_moves_global); ASSERT_EQ(actual.initial_partitioning.refinement.fm.rollback_parallel, expected.initial_partitioning.refinement.fm.rollback_parallel); ASSERT_EQ(actual.initial_partitioning.refinement.fm.iter_moves_on_recalc, @@ -349,8 +343,6 @@ TEST(AContext, LoadsQualityPresetCorrectly) { expected.refinement.fm.min_improvement); ASSERT_EQ(actual.refinement.fm.time_limit_factor, expected.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.refinement.fm.perform_moves_global, - expected.refinement.fm.perform_moves_global); ASSERT_EQ(actual.refinement.fm.rollback_parallel, expected.refinement.fm.rollback_parallel); ASSERT_EQ(actual.refinement.fm.iter_moves_on_recalc, @@ -650,8 +642,6 @@ TEST(AContext, LoadsHighestQualityPresetCorrectly) { expected.initial_partitioning.refinement.fm.min_improvement); ASSERT_EQ(actual.initial_partitioning.refinement.fm.time_limit_factor, expected.initial_partitioning.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.initial_partitioning.refinement.fm.perform_moves_global, - expected.initial_partitioning.refinement.fm.perform_moves_global); ASSERT_EQ(actual.initial_partitioning.refinement.fm.rollback_parallel, expected.initial_partitioning.refinement.fm.rollback_parallel); ASSERT_EQ(actual.initial_partitioning.refinement.fm.iter_moves_on_recalc, @@ -707,8 +697,6 @@ TEST(AContext, LoadsHighestQualityPresetCorrectly) { expected.refinement.fm.min_improvement); ASSERT_EQ(actual.refinement.fm.time_limit_factor, expected.refinement.fm.time_limit_factor); - ASSERT_EQ(actual.refinement.fm.perform_moves_global, - expected.refinement.fm.perform_moves_global); ASSERT_EQ(actual.refinement.fm.rollback_parallel, expected.refinement.fm.rollback_parallel); ASSERT_EQ(actual.refinement.fm.iter_moves_on_recalc, diff --git a/tests/partition/refinement/multitry_fm_test.cc b/tests/partition/refinement/multitry_fm_test.cc index 411e08ccd..4fc0205e1 100644 --- a/tests/partition/refinement/multitry_fm_test.cc +++ b/tests/partition/refinement/multitry_fm_test.cc @@ -188,7 +188,6 @@ TYPED_TEST(MultiTryFMTest, DoesNotWorsenSolutionQuality) { TYPED_TEST(MultiTryFMTest, AlsoWorksWithNonDefaultFeatures) { this->context.refinement.fm.obey_minimal_parallelism = true; this->context.refinement.fm.rollback_parallel = false; - this->context.refinement.fm.perform_moves_global = true; HyperedgeWeight objective_before = metrics::quality(this->partitioned_hypergraph, this->context.partition.objective); mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(this->partitioned_hypergraph); this->refiner->refine(phg, {}, this->metrics, std::numeric_limits::max()); From 9114ab973f9cfd049fb67606c84b2f62c4f493d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gottesb=C3=BCren?= Date: Mon, 4 Sep 2023 14:10:29 +0200 Subject: [PATCH 04/18] [FM refactoring] perform fixed vertex check slightly deepter --> halve compilation time --- .../refinement/fm/localized_kway_fm_core.cpp | 15 ++++++++------- .../refinement/fm/localized_kway_fm_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp index 263bfbc39..10a1fdb34 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp @@ -52,11 +52,7 @@ namespace mt_kahypar { deltaPhg.clear(); deltaPhg.setPartitionedHypergraph(&phg); delta_gain_cache.clear(); - if ( phg.hasFixedVertices() ) { - internalFindMoves(phg, fm_strategy); - } else { - internalFindMoves(phg, fm_strategy); - } + internalFindMoves(phg, fm_strategy); return true; } else { return false; @@ -113,7 +109,7 @@ namespace mt_kahypar { template - template + template void LocalizedKWayFM::internalFindMoves(PartitionedHypergraph& phg, DispatchedFMStrategy& fm_strategy) { StopRule stopRule(phg.initialNumNodes()); @@ -203,7 +199,12 @@ namespace mt_kahypar { break; } - acquireOrUpdateNeighbors(deltaPhg, delta_gain_cache, move, fm_strategy); + if (phg.hasFixedVertices()) { + acquireOrUpdateNeighbors(deltaPhg, delta_gain_cache, move, fm_strategy); + } else { + acquireOrUpdateNeighbors(deltaPhg, delta_gain_cache, move, fm_strategy); + } + } } diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h index dc6076ad8..d8fed1bbf 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h @@ -88,7 +88,7 @@ class LocalizedKWayFM { FMStats stats; private: - template + template void internalFindMoves(PartitionedHypergraph& phg, DispatchedFMStrategy& fm_strategy); template From 8d93a6bf1bbb1dd48ee84bf23c63ab6331c9c5d9 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 7 Sep 2023 17:00:24 +0200 Subject: [PATCH 05/18] optimize FM neighbor acquiration for graphs --- .../refinement/fm/localized_kway_fm_core.cpp | 55 +++++++++++-------- .../refinement/fm/localized_kway_fm_core.h | 4 +- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp index 10a1fdb34..e3c988bbc 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp @@ -78,32 +78,43 @@ namespace mt_kahypar { MT_KAHYPAR_ATTRIBUTE_ALWAYS_INLINE void LocalizedKWayFM::acquireOrUpdateNeighbors(PHG& phg, CACHE& gain_cache, const Move& move, DispatchedFMStrategy& fm_strategy) { - // Note: In theory we should acquire/update all neighbors. It just turned out that this works fine - // Actually: only vertices incident to edges with gain changes can become new boundary vertices. - // Vertices that already were boundary vertices, can still be considered later since they are in the task queue - // --> actually not that bad - for (HyperedgeID e : edgesWithGainChanges) { - if (phg.edgeSize(e) < context.partition.ignore_hyperedge_size_threshold) { - for (HypernodeID v : phg.pins(e)) { - if constexpr ( has_fixed_vertices ) { - if ( phg.isFixed(v) ) continue; - } - if (neighborDeduplicator[v] != deduplicationTime) { - SearchID searchOfV = sharedData.nodeTracker.searchOfNode[v].load(std::memory_order_relaxed); - if (searchOfV == thisSearch) { - fm_strategy.updateGain(phg, gain_cache, v, move); - } else if (sharedData.nodeTracker.tryAcquireNode(v, thisSearch)) { - fm_strategy.insertIntoPQ(phg, gain_cache, v); + auto updateOrAcquire = [&](const HypernodeID v) { + SearchID searchOfV = sharedData.nodeTracker.searchOfNode[v].load(std::memory_order_relaxed); + if (searchOfV == thisSearch) { + fm_strategy.updateGain(phg, gain_cache, v, move); + } else if (sharedData.nodeTracker.tryAcquireNode(v, thisSearch)) { + fm_strategy.insertIntoPQ(phg, gain_cache, v); + } + }; + + if constexpr (PartitionedHypergraph::is_graph) { + // simplified case for graphs: neighbors can't be duplicated + for (HyperedgeID e : phg.incidentEdges(move.node)) { + HypernodeID v = phg.edgeTarget(e); + if ( has_fixed_vertices && phg.isFixed(v) ) continue; + + updateOrAcquire(v); + } + } else { + // Note: only vertices incident to edges with gain changes can become new boundary vertices. + // Vertices that already were boundary vertices, can still be considered later since they are in the task queue + for (HyperedgeID e : edgesWithGainChanges) { + if (phg.edgeSize(e) < context.partition.ignore_hyperedge_size_threshold) { + for (HypernodeID v : phg.pins(e)) { + if ( has_fixed_vertices && phg.isFixed(v) ) continue; + + if (neighborDeduplicator[v] != deduplicationTime) { + updateOrAcquire(v); + neighborDeduplicator[v] = deduplicationTime; } - neighborDeduplicator[v] = deduplicationTime; } } } - } - if (++deduplicationTime == 0) { - neighborDeduplicator.assign(neighborDeduplicator.size(), 0); - deduplicationTime = 1; + if (++deduplicationTime == 0) { + neighborDeduplicator.assign(neighborDeduplicator.size(), 0); + deduplicationTime = 1; + } } } @@ -158,7 +169,7 @@ namespace mt_kahypar { } else { moved = deltaPhg.changeNodePart(move.node, move.from, move.to, allowed_weight, [&](const SynchronizedEdgeUpdate& sync_update) { - if (GainCache::triggersDeltaGainUpdate(sync_update)) { + if (!PartitionedHypergraph::is_graph && GainCache::triggersDeltaGainUpdate(sync_update)) { edgesWithGainChanges.push_back(sync_update.he); } delta_gain_cache.deltaGainUpdate(deltaPhg, sync_update); diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h index d8fed1bbf..a2747772b 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h @@ -62,7 +62,7 @@ class LocalizedKWayFM { context(context), thisSearch(0), deltaPhg(context), - neighborDeduplicator(numNodes, 0), + neighborDeduplicator(PartitionedHypergraph::is_graph ? 0 : numNodes, 0), gain_cache(gainCache), delta_gain_cache(gainCache), sharedData(sharedData), @@ -113,7 +113,7 @@ class LocalizedKWayFM { // ! Used after a move. Stores whether a neighbor of the just moved vertex has already been updated. vec neighborDeduplicator; - HypernodeID deduplicationTime = 0; + HypernodeID deduplicationTime = 1; // ! Stores hyperedges whose pins's gains may have changed after vertex move vec edgesWithGainChanges; From c1b3180ff2ab77783717e1deaaab089930eee6fc Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Fri, 8 Sep 2023 14:36:49 +0200 Subject: [PATCH 06/18] proper initialization for rebalancer --- mt-kahypar/partition/coarsening/multilevel_uncoarsener.cpp | 4 ++++ mt-kahypar/partition/coarsening/nlevel_uncoarsener.cpp | 3 +++ mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp | 2 -- .../label_propagation/label_propagation_refiner.cpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mt-kahypar/partition/coarsening/multilevel_uncoarsener.cpp b/mt-kahypar/partition/coarsening/multilevel_uncoarsener.cpp index c65b6967d..39197062f 100644 --- a/mt-kahypar/partition/coarsening/multilevel_uncoarsener.cpp +++ b/mt-kahypar/partition/coarsening/multilevel_uncoarsener.cpp @@ -211,6 +211,10 @@ namespace mt_kahypar { improvement_found = false; const HyperedgeWeight metric_before = _current_metrics.quality; + if ( _rebalancer && _context.refinement.rebalancer != RebalancingAlgorithm::do_nothing ) { + _rebalancer->initialize(phg); + } + if ( _label_propagation && _context.refinement.label_propagation.algorithm != LabelPropagationAlgorithm::do_nothing ) { _timer.start_timer("initialize_lp_refiner", "Initialize LP Refiner"); _label_propagation->initialize(phg); diff --git a/mt-kahypar/partition/coarsening/nlevel_uncoarsener.cpp b/mt-kahypar/partition/coarsening/nlevel_uncoarsener.cpp index 8ede126d0..1cca04fbe 100644 --- a/mt-kahypar/partition/coarsening/nlevel_uncoarsener.cpp +++ b/mt-kahypar/partition/coarsening/nlevel_uncoarsener.cpp @@ -95,6 +95,9 @@ namespace mt_kahypar { // Initialize Refiner mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(*_uncoarseningData.partitioned_hg); + if ( _rebalancer ) { + _rebalancer->initialize(phg); + } if ( _label_propagation ) { _label_propagation->initialize(phg); } diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp index 76658de52..1dad19ad7 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp @@ -427,8 +427,6 @@ namespace mt_kahypar { if (!gain_cache.isInitialized()) { gain_cache.initializeGainCache(phg); } - rebalancer.initialize(hypergraph); - is_initialized = true; } diff --git a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp index bb00e39b3..b86fc3e1f 100644 --- a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp +++ b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp @@ -316,7 +316,7 @@ namespace mt_kahypar { template void LabelPropagationRefiner::initializeImpl(mt_kahypar_partitioned_hypergraph_t& phg) { - _rebalancer.initialize(phg); // TODO: probably wrong place for this + unused(phg); } template From b885c82700b5445a5ae45378d21b02262db10309 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 28 Sep 2023 13:36:01 +0200 Subject: [PATCH 07/18] remove is_initialized flag from kway FM --- mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp | 7 ------- mt-kahypar/partition/refinement/fm/multitry_kway_fm.h | 1 - 2 files changed, 8 deletions(-) diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp index 1dad19ad7..267ced6d4 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp @@ -84,8 +84,6 @@ namespace mt_kahypar { Metrics& metrics, const double time_limit) { PartitionedHypergraph& phg = utils::cast(hypergraph); - - if (!is_initialized) throw std::runtime_error("Call initialize on fm before calling refine"); resizeDataStructuresForCurrentK(); Gain overall_improvement = 0; @@ -219,10 +217,6 @@ namespace mt_kahypar { printMemoryConsumption(); } - if ( !context.isNLevelPartitioning() ) { - is_initialized = false; - } - metrics.quality -= overall_improvement; metrics.imbalance = metrics::imbalance(phg, context); HEAVY_REFINEMENT_ASSERT(phg.checkTrackedPartitionInformation(gain_cache)); @@ -427,7 +421,6 @@ namespace mt_kahypar { if (!gain_cache.isInitialized()) { gain_cache.initializeGainCache(phg); } - is_initialized = true; } template diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h index 32547674e..6cf0ef357 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h @@ -117,7 +117,6 @@ class MultiTryKWayFM final : public IRefiner { void resizeDataStructuresForCurrentK(); - bool is_initialized = false; bool enable_light_fm = false; const HypernodeID initial_num_nodes; const Context& context; From 3abe4f95e1de1593b7bc7fbf23201facc805df61 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 28 Sep 2023 16:49:40 +0200 Subject: [PATCH 08/18] fix warnings for redefined macros --- mt-kahypar/macros.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mt-kahypar/macros.h b/mt-kahypar/macros.h index 2436b9a47..0f9f1f136 100644 --- a/mt-kahypar/macros.h +++ b/mt-kahypar/macros.h @@ -121,6 +121,9 @@ // In windows unisgned long != size_t #define UL(X) (size_t) X +#ifdef STR +#undef STR +#endif #define STR(X) std::to_string(X) #define STREAM2STR(X) static_cast(X).str(); @@ -133,6 +136,9 @@ #define BOLD "\033[1m" #define END "\033[0m" #define INFO(msg) LOG << CYAN << "[INFO]" << END << msg +#ifdef WARNING +#undef WARNING +#endif #define WARNING(msg) LOG << YELLOW << "[WARNING]" << END << msg #define ERR(msg) LOG << RED << "[ERROR]" << END << msg; std::exit(-1) From c6b731b69fc55a3870b2b157ff6b7cb637254d18 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Fri, 8 Sep 2023 16:16:31 +0200 Subject: [PATCH 09/18] [compile time] disable ALWAYS_INLINE in debug mode ~7% overall speedup with all features --- mt-kahypar/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mt-kahypar/macros.h b/mt-kahypar/macros.h index 0f9f1f136..46bb413ef 100644 --- a/mt-kahypar/macros.h +++ b/mt-kahypar/macros.h @@ -59,7 +59,7 @@ template \ std::enable_if_t -#if defined(__GNUC__) || defined(__clang__) +#if (defined(__GNUC__) || defined(__clang__)) && defined(NDEBUG) #define MT_KAHYPAR_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) inline #else #define MT_KAHYPAR_ATTRIBUTE_ALWAYS_INLINE From ffa7eed94f28bc1cf22205f07d7734ffaf25f2e8 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Tue, 12 Sep 2023 16:34:04 +0200 Subject: [PATCH 10/18] [compile time] machinery for unfolding only valid type trait/gain combinations --- .../refinement/gains/gain_definitions.h | 81 +++++++++++++++++++ .../register_refinement_algorithms.cpp | 18 ++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/mt-kahypar/partition/refinement/gains/gain_definitions.h b/mt-kahypar/partition/refinement/gains/gain_definitions.h index f52d7addb..610fada88 100644 --- a/mt-kahypar/partition/refinement/gains/gain_definitions.h +++ b/mt-kahypar/partition/refinement/gains/gain_definitions.h @@ -132,6 +132,19 @@ struct SteinerTreeForGraphsTypes : public kahypar::meta::PolicyBase { #endif #endif +template +struct CombinedTraits : public kahypar::meta::PolicyBase { + using Hypergraph = typename TypeTraits::Hypergraph; + using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + + using GainComputation = typename GainTypes::GainComputation; + using AttributedGains = typename GainTypes::AttributedGains; + using GainCache = typename GainTypes::GainCache; + using DeltaGainCache = typename GainTypes::DeltaGainCache; + using Rollback = typename GainTypes::Rollback; + using FlowNetworkConstruction = typename GainTypes::FlowNetworkConstruction; +}; + using GainTypes = kahypar::meta::Typelist; +#define _LIST_HYPERGRAPH_COMBINATIONS(TYPE_TRAITS) \ + CombinedTraits, \ + CombinedTraits \ + ENABLE_SOED(COMMA CombinedTraits) \ + ENABLE_STEINER_TREE(COMMA CombinedTraits) + +#define _LIST_GRAPH_COMBINATIONS(TYPE_TRAITS) \ + CombinedTraits \ + ENABLE_STEINER_TREE(COMMA CombinedTraits) + +using ValidTraitCombinations = kahypar::meta::Typelist<_LIST_HYPERGRAPH_COMBINATIONS(StaticHypergraphTypeTraits) + ENABLE_GRAPHS(COMMA _LIST_GRAPH_COMBINATIONS(StaticGraphTypeTraits)) + ENABLE_HIGHEST_QUALITY(COMMA _LIST_HYPERGRAPH_COMBINATIONS(DynamicHypergraphTypeTraits)) + ENABLE_HIGHEST_QUALITY_FOR_GRAPHS(COMMA _LIST_GRAPH_COMBINATIONS(DynamicGraphTypeTraits)) + ENABLE_LARGE_K(COMMA _LIST_HYPERGRAPH_COMBINATIONS(LargeKHypergraphTypeTraits))>; + + +#define _INSTANTIATE_CLASS_MACRO_FOR_HYPERGRAPH_COMBINATIONS(C, TYPE_TRAITS) \ + template class C(CombinedTraits); \ + template class C(CombinedTraits); \ + ENABLE_SOED(template class C(CombinedTraits);) \ + ENABLE_STEINER_TREE(template class C(CombinedTraits);) + +#define _INSTANTIATE_CLASS_MACRO_FOR_GRAPH_COMBINATIONS(C, TYPE_TRAITS) \ + template class C(CombinedTraits); \ + ENABLE_STEINER_TREE(template class C(CombinedTraits);) + + +#define INSTANTIATE_CLASS_WITH_VALID_TRAITS(C) \ + _INSTANTIATE_CLASS_MACRO_FOR_HYPERGRAPH_COMBINATIONS(C, StaticHypergraphTypeTraits) \ + ENABLE_GRAPHS(_INSTANTIATE_CLASS_MACRO_FOR_GRAPH_COMBINATIONS(C, StaticGraphTypeTraits)) \ + ENABLE_HIGHEST_QUALITY(_INSTANTIATE_CLASS_MACRO_FOR_HYPERGRAPH_COMBINATIONS(C, DynamicHypergraphTypeTraits)) \ + ENABLE_HIGHEST_QUALITY_FOR_GRAPHS(_INSTANTIATE_CLASS_MACRO_FOR_GRAPH_COMBINATIONS(C, DynamicGraphTypeTraits)) \ + ENABLE_LARGE_K(_INSTANTIATE_CLASS_MACRO_FOR_HYPERGRAPH_COMBINATIONS(C, LargeKHypergraphTypeTraits)) + + #define INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(C) \ INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, Km1GainTypes) \ INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, CutGainTypes) \ @@ -148,4 +197,36 @@ using GainTypes = kahypar::meta::Typelist traits; \ + return traits; \ +} + +#define SWITCH_HYPERGRAPH_GAIN_TYPES(TYPE_TRAITS, gain_policy) { \ + switch ( gain_policy ) { \ + case GainPolicy::km1: _RETURN_COMBINED_POLICY(TYPE_TRAITS, Km1GainTypes) \ + case GainPolicy::cut: _RETURN_COMBINED_POLICY(TYPE_TRAITS, CutGainTypes) \ + case GainPolicy::soed: ENABLE_SOED(_RETURN_COMBINED_POLICY(TYPE_TRAITS, SoedGainTypes)) \ + case GainPolicy::steiner_tree: \ + ENABLE_STEINER_TREE(_RETURN_COMBINED_POLICY(TYPE_TRAITS, SteinerTreeGainTypes)) \ + default: { \ + ERROR("Invalid gain policy type"); \ + } \ + } \ +} + +#define SWITCH_GRAPH_GAIN_TYPES(TYPE_TRAITS, gain_policy) { \ + switch ( gain_policy ) { \ + case GainPolicy::cut_for_graphs: \ + ENABLE_GRAPHS(_RETURN_COMBINED_POLICY(TYPE_TRAITS, CutGainForGraphsTypes)) \ + case GainPolicy::steiner_tree_for_graphs: \ + ENABLE_STEINER_TREE(ENABLE_GRAPHS(_RETURN_COMBINED_POLICY(TYPE_TRAITS, SteinerTreeForGraphsTypes))) \ + default: { \ + ERROR("Invalid gain policy type"); \ + } \ + } \ +} + } // namespace mt_kahypar diff --git a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp index 9a3684030..f0c707e6e 100644 --- a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp +++ b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp @@ -26,11 +26,12 @@ ******************************************************************************/ #include "kahypar-resources/meta/registrar.h" -#include "mt-kahypar/partition/context.h" +#include "mt-kahypar/partition/context.h" #include "mt-kahypar/partition/factories.h" #include "mt-kahypar/partition/refinement/do_nothing_refiner.h" #include "mt-kahypar/partition/refinement/flows/do_nothing_refiner.h" +#include "mt-kahypar/partition/refinement/gains/gain_definitions.h" #define REGISTER_DISPATCHED_LP_REFINER(id, dispatcher, ...) \ static kahypar::meta::Registrar register_ ## dispatcher( \ @@ -134,6 +135,21 @@ }) namespace mt_kahypar { +kahypar::meta::PolicyBase& getCombinedTraitsPolicy(mt_kahypar_partition_type_t partition_type, GainPolicy gain_policy) { + switch ( partition_type ) { + case MULTILEVEL_HYPERGRAPH_PARTITIONING: SWITCH_HYPERGRAPH_GAIN_TYPES(StaticHypergraphTypeTraits, gain_policy); + case MULTILEVEL_GRAPH_PARTITIONING: SWITCH_GRAPH_GAIN_TYPES(StaticGraphTypeTraits, gain_policy); + case N_LEVEL_HYPERGRAPH_PARTITIONING: SWITCH_HYPERGRAPH_GAIN_TYPES(DynamicHypergraphTypeTraits, gain_policy); + case N_LEVEL_GRAPH_PARTITIONING: SWITCH_GRAPH_GAIN_TYPES(DynamicGraphTypeTraits, gain_policy); + case LARGE_K_PARTITIONING: SWITCH_HYPERGRAPH_GAIN_TYPES(LargeKHypergraphTypeTraits, gain_policy); + default: { + LOG << "Invalid partition type"; + std::exit(-1); + } + } +} + + REGISTER_DISPATCHED_LP_REFINER(LabelPropagationAlgorithm::label_propagation, LabelPropagationDispatcher, kahypar::meta::PolicyRegistry::getInstance().getPolicy( From 9d2d89ba3a43dc4c5b197a9305a765632824fa44 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Tue, 12 Sep 2023 17:13:20 +0200 Subject: [PATCH 11/18] [compile time] use reduced unfolding for refiners ~14% overall speedup with all features --- mt-kahypar/definitions.h | 14 ---- mt-kahypar/partition/factories.h | 16 ++-- .../refinement/flows/flow_refiner.cpp | 26 +++--- .../partition/refinement/flows/flow_refiner.h | 8 +- .../flows/parallel_construction.cpp | 80 +++++++++---------- .../refinement/flows/parallel_construction.h | 6 +- .../partition/refinement/flows/scheduler.cpp | 33 ++++---- .../partition/refinement/flows/scheduler.h | 9 ++- .../flows/sequential_construction.cpp | 72 ++++++++--------- .../flows/sequential_construction.h | 6 +- .../partition/refinement/fm/fm_commons.cpp | 12 +-- .../partition/refinement/fm/fm_commons.h | 16 ++-- .../refinement/fm/global_rollback.cpp | 46 +++++------ .../partition/refinement/fm/global_rollback.h | 10 +-- .../refinement/fm/localized_kway_fm_core.cpp | 38 ++++----- .../refinement/fm/localized_kway_fm_core.h | 10 +-- .../refinement/fm/multitry_kway_fm.cpp | 53 ++++++------ .../refinement/fm/multitry_kway_fm.h | 10 +-- .../fm/strategies/gain_cache_strategy.h | 6 +- .../fm/strategies/unconstrained_strategy.h | 6 +- .../refinement/gains/gain_definitions.h | 14 +--- .../label_propagation_refiner.cpp | 75 +++++++++-------- .../label_propagation_refiner.h | 10 +-- .../rebalancing/advanced_rebalancer.cpp | 62 +++++++------- .../rebalancing/advanced_rebalancer.h | 10 +-- .../rebalancing/simple_rebalancer.cpp | 18 ++--- .../rebalancing/simple_rebalancer.h | 8 +- .../register_refinement_algorithms.cpp | 49 +++--------- .../refinement/advanced_rebalancer_test.cc | 6 +- .../refinement/flow_construction_test.cc | 8 +- .../label_propagation_refiner_test.cc | 7 +- .../partition/refinement/multitry_fm_test.cc | 7 +- tests/partition/refinement/rebalance_test.cc | 2 +- tests/partition/refinement/rollback_test.cc | 4 +- tests/partition/refinement/scheduler_test.cc | 16 ++-- 35 files changed, 361 insertions(+), 412 deletions(-) diff --git a/mt-kahypar/definitions.h b/mt-kahypar/definitions.h index d494950e1..9f0fc7e20 100644 --- a/mt-kahypar/definitions.h +++ b/mt-kahypar/definitions.h @@ -110,13 +110,6 @@ using TypeTraitsList = kahypar::meta::Typelist;) \ ENABLE_HIGHEST_QUALITY_FOR_GRAPHS(template class C;) -#define INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS(C) \ - template class C(StaticHypergraphTypeTraits); \ - ENABLE_GRAPHS(template class C(StaticGraphTypeTraits);) \ - ENABLE_HIGHEST_QUALITY(template class C(DynamicHypergraphTypeTraits);) \ - ENABLE_HIGHEST_QUALITY_FOR_GRAPHS(template class C(DynamicGraphTypeTraits);) \ - ENABLE_LARGE_K(template class C(LargeKHypergraphTypeTraits);) - #define INSTANTIATE_CLASS_WITH_TYPE_TRAITS(C) \ template class C; \ ENABLE_GRAPHS(template class C;) \ @@ -124,13 +117,6 @@ using TypeTraitsList = kahypar::meta::Typelist;) \ ENABLE_LARGE_K(template class C;) -#define INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, Other) \ - template class C(StaticHypergraphTypeTraits, Other); \ - ENABLE_GRAPHS(template class C(StaticGraphTypeTraits, Other);) \ - ENABLE_HIGHEST_QUALITY(template class C(DynamicHypergraphTypeTraits, Other);) \ - ENABLE_HIGHEST_QUALITY_FOR_GRAPHS(template class C(DynamicGraphTypeTraits, Other);) \ - ENABLE_LARGE_K(template class C(LargeKHypergraphTypeTraits, Other);) - using HighResClockTimepoint = std::chrono::time_point; diff --git a/mt-kahypar/partition/factories.h b/mt-kahypar/partition/factories.h index a39026dad..9de7b9d4d 100644 --- a/mt-kahypar/partition/factories.h +++ b/mt-kahypar/partition/factories.h @@ -88,7 +88,7 @@ using LabelPropagationFactory = kahypar::meta::Factory>; + kahypar::meta::Typelist>; using DeterministicLabelPropagationDispatcher = kahypar::meta::StaticMultiDispatchFactory< DeterministicLabelPropagationRefiner, @@ -101,7 +101,7 @@ using FMFactory = kahypar::meta::Factory>; + kahypar::meta::Typelist>; using UnconstrainedFMDispatcher = DefaultFMDispatcher; @@ -110,12 +110,12 @@ using FMStrategyFactory = kahypar::meta::Factory>; + kahypar::meta::Typelist>; using UnconstrainedFMStrategyDispatcher = kahypar::meta::StaticMultiDispatchFactory< UnconstrainedStrategy, IFMStrategy, - kahypar::meta::Typelist>; + kahypar::meta::Typelist>; using FlowSchedulerFactory = kahypar::meta::Factory; @@ -123,19 +123,19 @@ using FlowSchedulerFactory = kahypar::meta::Factory>; + kahypar::meta::Typelist>; using RebalancerFactory = kahypar::meta::Factory; using SimpleRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< SimpleRebalancer, IRebalancer, - kahypar::meta::Typelist>; + kahypar::meta::Typelist>; using AdvancedRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< AdvancedRebalancer, IRebalancer, - kahypar::meta::Typelist>; + kahypar::meta::Typelist>; using FlowRefinementFactory = kahypar::meta::Factory; @@ -143,5 +143,5 @@ using FlowRefinementFactory = kahypar::meta::Factory>; + kahypar::meta::Typelist>; } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/flows/flow_refiner.cpp b/mt-kahypar/partition/refinement/flows/flow_refiner.cpp index 482469b96..eef53bbc7 100644 --- a/mt-kahypar/partition/refinement/flows/flow_refiner.cpp +++ b/mt-kahypar/partition/refinement/flows/flow_refiner.cpp @@ -35,10 +35,10 @@ namespace mt_kahypar { -template -MoveSequence FlowRefiner::refineImpl(mt_kahypar_partitioned_hypergraph_const_t& hypergraph, - const Subhypergraph& sub_hg, - const HighResClockTimepoint& start) { +template +MoveSequence FlowRefiner::refineImpl(mt_kahypar_partitioned_hypergraph_const_t& hypergraph, + const Subhypergraph& sub_hg, + const HighResClockTimepoint& start) { const PartitionedHypergraph& phg = utils::cast_const(hypergraph); MoveSequence sequence { { }, 0 }; utils::Timer& timer = utils::Utilities::instance().getTimer(_context.utility_id); @@ -101,10 +101,10 @@ MoveSequence FlowRefiner::refineImpl(mt_kahypar_partition #define NOW std::chrono::high_resolution_clock::now() #define RUNNING_TIME(X) std::chrono::duration(NOW - X).count(); -template -bool FlowRefiner::runFlowCutter(const FlowProblem& flow_problem, - const HighResClockTimepoint& start, - bool& time_limit_reached) { +template +bool FlowRefiner::runFlowCutter(const FlowProblem& flow_problem, + const HighResClockTimepoint& start, + bool& time_limit_reached) { whfc::Node s = flow_problem.source; whfc::Node t = flow_problem.sink; bool result = false; @@ -146,9 +146,9 @@ bool FlowRefiner::runFlowCutter(const FlowProblem& flow_p return result; } -template -FlowProblem FlowRefiner::constructFlowHypergraph(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg) { +template +FlowProblem FlowRefiner::constructFlowHypergraph(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg) { _block_0 = sub_hg.block_0; _block_1 = sub_hg.block_1; ASSERT(_block_0 != kInvalidPartition && _block_1 != kInvalidPartition); @@ -173,9 +173,9 @@ FlowProblem FlowRefiner::constructFlowHypergraph(const Pa } namespace { -#define FLOW_REFINER(X, Y) FlowRefiner +#define FLOW_REFINER(X) FlowRefiner } -INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(FLOW_REFINER) +INSTANTIATE_CLASS_WITH_VALID_TRAITS(FLOW_REFINER) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/flows/flow_refiner.h b/mt-kahypar/partition/refinement/flows/flow_refiner.h index 9383f85af..e31171f22 100644 --- a/mt-kahypar/partition/refinement/flows/flow_refiner.h +++ b/mt-kahypar/partition/refinement/flows/flow_refiner.h @@ -45,12 +45,12 @@ namespace mt_kahypar { -template +template class FlowRefiner final : public IFlowRefiner { static constexpr bool debug = false; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; public: explicit FlowRefiner(const HyperedgeID num_hyperedges, @@ -128,7 +128,7 @@ class FlowRefiner final : public IFlowRefiner { whfc::HyperFlowCutter _parallel_hfc; vec _whfc_to_node; - SequentialConstruction _sequential_construction; - ParallelConstruction _parallel_construction; + SequentialConstruction _sequential_construction; + ParallelConstruction _parallel_construction; }; } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/flows/parallel_construction.cpp b/mt-kahypar/partition/refinement/flows/parallel_construction.cpp index ad74b4b95..f79f16f12 100644 --- a/mt-kahypar/partition/refinement/flows/parallel_construction.cpp +++ b/mt-kahypar/partition/refinement/flows/parallel_construction.cpp @@ -36,10 +36,10 @@ namespace mt_kahypar { -template -typename ParallelConstruction::TmpHyperedge -ParallelConstruction::DynamicIdenticalNetDetection::get( - const size_t he_hash, const vec& pins) { +template +typename ParallelConstruction::TmpHyperedge +ParallelConstruction::DynamicIdenticalNetDetection::get(const size_t he_hash, + const vec& pins) { const size_t bucket_idx = he_hash % _hash_buckets.size(); if ( __atomic_load_n(&_hash_buckets[bucket_idx].threshold, __ATOMIC_RELAXED) == _threshold ) { // There exists already some hyperedges with the same hash @@ -65,8 +65,8 @@ ParallelConstruction::DynamicIdenticalNetDetection::get( return TmpHyperedge { 0, std::numeric_limits::max(), whfc::invalidHyperedge }; } -template -void ParallelConstruction::DynamicIdenticalNetDetection::add(const TmpHyperedge& tmp_he) { +template +void ParallelConstruction::DynamicIdenticalNetDetection::add(const TmpHyperedge& tmp_he) { const size_t bucket_idx = tmp_he.hash % _hash_buckets.size(); uint32_t expected = __atomic_load_n(&_hash_buckets[bucket_idx].threshold, __ATOMIC_RELAXED); uint32_t desired = _threshold - 1; @@ -81,12 +81,12 @@ void ParallelConstruction::DynamicIdenticalNetDetection:: _hash_buckets[bucket_idx].identical_nets.push_back(ThresholdHyperedge { tmp_he, _threshold }); } -template -FlowProblem ParallelConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem ParallelConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { FlowProblem flow_problem; const double density = static_cast(phg.initialNumEdges()) / phg.initialNumNodes(); const double avg_he_size = static_cast(phg.initialNumPins()) / phg.initialNumEdges(); @@ -126,13 +126,13 @@ FlowProblem ParallelConstruction::constructFlowHypergraph return flow_problem; } -template -FlowProblem ParallelConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node, - const bool default_construction) { +template +FlowProblem ParallelConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node, + const bool default_construction) { FlowProblem flow_problem; if ( default_construction ) { // This algorithm iterates over all hyperedges and checks for all pins if @@ -170,12 +170,12 @@ FlowProblem ParallelConstruction::constructFlowHypergraph return flow_problem; } -template -FlowProblem ParallelConstruction::constructDefault(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem ParallelConstruction::constructDefault(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { ASSERT(block_0 != kInvalidPartition && block_1 != kInvalidPartition); FlowProblem flow_problem; flow_problem.total_cut = 0; @@ -334,12 +334,12 @@ FlowProblem ParallelConstruction::constructDefault(const return flow_problem; } -template -FlowProblem ParallelConstruction::constructOptimizedForLargeHEs(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem ParallelConstruction::constructOptimizedForLargeHEs(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { ASSERT(block_0 != kInvalidPartition && block_1 != kInvalidPartition); FlowProblem flow_problem; flow_problem.total_cut = 0; @@ -565,13 +565,13 @@ class BFSQueue { }; } -template -void ParallelConstruction::determineDistanceFromCut(const PartitionedHypergraph& phg, - const whfc::Node source, - const whfc::Node sink, - const PartitionID block_0, - const PartitionID block_1, - const vec& whfc_to_node) { +template +void ParallelConstruction::determineDistanceFromCut(const PartitionedHypergraph& phg, + const whfc::Node source, + const whfc::Node sink, + const PartitionID block_0, + const PartitionID block_1, + const vec& whfc_to_node) { auto& distances = _hfc.cs.border_nodes.distance; distances.assign(_flow_hg.numNodes(), whfc::HopDistance(0)); _visited_hns.resize(_flow_hg.numNodes() + _flow_hg.numHyperedges()); @@ -640,9 +640,9 @@ void ParallelConstruction::determineDistanceFromCut(const } namespace { -#define PARALLEL_CONSTRUCTION(X, Y) ParallelConstruction +#define PARALLEL_CONSTRUCTION(X) ParallelConstruction } -INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(PARALLEL_CONSTRUCTION) +INSTANTIATE_CLASS_WITH_VALID_TRAITS(PARALLEL_CONSTRUCTION) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/flows/parallel_construction.h b/mt-kahypar/partition/refinement/flows/parallel_construction.h index 3f7c90c02..7c47f87fc 100644 --- a/mt-kahypar/partition/refinement/flows/parallel_construction.h +++ b/mt-kahypar/partition/refinement/flows/parallel_construction.h @@ -45,15 +45,15 @@ namespace mt_kahypar { struct FlowProblem; -template +template class ParallelConstruction { static constexpr bool debug = false; static constexpr size_t NUM_CSR_BUCKETS = 1024; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using FlowNetworkConstruction = typename GainTypes::FlowNetworkConstruction; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using FlowNetworkConstruction = typename CombinedTraits::FlowNetworkConstruction; struct TmpPin { HyperedgeID e; diff --git a/mt-kahypar/partition/refinement/flows/scheduler.cpp b/mt-kahypar/partition/refinement/flows/scheduler.cpp index 57f7006aa..bf9641a91 100644 --- a/mt-kahypar/partition/refinement/flows/scheduler.cpp +++ b/mt-kahypar/partition/refinement/flows/scheduler.cpp @@ -35,8 +35,8 @@ namespace mt_kahypar { -template -void FlowRefinementScheduler::RefinementStats::update_global_stats() { +template +void FlowRefinementScheduler::RefinementStats::update_global_stats() { _stats.update_stat("num_flow_refinements", num_refinements.load(std::memory_order_relaxed)); _stats.update_stat("num_flow_improvement", @@ -57,8 +57,8 @@ void FlowRefinementScheduler::RefinementStats::update_glo total_improvement.load(std::memory_order_relaxed)); } -template -bool FlowRefinementScheduler::refineImpl( +template +bool FlowRefinementScheduler::refineImpl( mt_kahypar_partitioned_hypergraph_t& hypergraph, const parallel::scalable_vector&, Metrics& best_metrics, @@ -150,8 +150,8 @@ bool FlowRefinementScheduler::refineImpl( return overall_delta.load(std::memory_order_relaxed) < 0; } -template -void FlowRefinementScheduler::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { +template +void FlowRefinementScheduler::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { PartitionedHypergraph& phg = utils::cast(hypergraph); _phg = &phg; resizeDataStructuresForCurrentK(); @@ -175,8 +175,8 @@ void FlowRefinementScheduler::initializeImpl(mt_kahypar_p _refiner.initialize(max_parallism); } -template -void FlowRefinementScheduler::resizeDataStructuresForCurrentK() { +template +void FlowRefinementScheduler::resizeDataStructuresForCurrentK() { if ( _current_k != _context.partition.k ) { _current_k = _context.partition.k; // Note that in general changing the number of blocks should not resize @@ -269,9 +269,8 @@ void addCutHyperedgesToQuotientGraph(QuotientGraph& quotient_graph, } // namespace -template -HyperedgeWeight FlowRefinementScheduler::applyMoves(const SearchID search_id, - MoveSequence& sequence) { +template +HyperedgeWeight FlowRefinementScheduler::applyMoves(const SearchID search_id, MoveSequence& sequence) { unused(search_id); ASSERT(_phg); @@ -360,10 +359,10 @@ HyperedgeWeight FlowRefinementScheduler::applyMoves(const return improvement; } -template -typename FlowRefinementScheduler::PartWeightUpdateResult -FlowRefinementScheduler::partWeightUpdate(const vec& part_weight_deltas, - const bool rollback) { +template +typename FlowRefinementScheduler::PartWeightUpdateResult +FlowRefinementScheduler::partWeightUpdate(const vec& part_weight_deltas, + const bool rollback) { const HypernodeWeight multiplier = rollback ? -1 : 1; PartWeightUpdateResult res; _part_weights_lock.lock(); @@ -391,9 +390,9 @@ FlowRefinementScheduler::partWeightUpdate(const vec +#define FLOW_REFINEMENT_SCHEDULER(X) FlowRefinementScheduler } -INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(FLOW_REFINEMENT_SCHEDULER) +INSTANTIATE_CLASS_WITH_VALID_TRAITS(FLOW_REFINEMENT_SCHEDULER) } diff --git a/mt-kahypar/partition/refinement/flows/scheduler.h b/mt-kahypar/partition/refinement/flows/scheduler.h index 0f0a353d2..3e4faea55 100644 --- a/mt-kahypar/partition/refinement/flows/scheduler.h +++ b/mt-kahypar/partition/refinement/flows/scheduler.h @@ -54,15 +54,16 @@ namespace { } } -template +template class FlowRefinementScheduler final : public IRefiner { static constexpr bool debug = false; static constexpr bool enable_heavy_assert = false; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using AttributedGains = typename GainTypes::AttributedGains; + using TypeTraits = typename CombinedTraits::TypeTraits; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using AttributedGains = typename CombinedTraits::AttributedGains; struct RefinementStats { RefinementStats(utils::Stats& stats) : diff --git a/mt-kahypar/partition/refinement/flows/sequential_construction.cpp b/mt-kahypar/partition/refinement/flows/sequential_construction.cpp index 5feda882d..dc237550b 100644 --- a/mt-kahypar/partition/refinement/flows/sequential_construction.cpp +++ b/mt-kahypar/partition/refinement/flows/sequential_construction.cpp @@ -34,8 +34,8 @@ namespace mt_kahypar { -template -whfc::Hyperedge SequentialConstruction::DynamicIdenticalNetDetection::add_if_not_contained( +template +whfc::Hyperedge SequentialConstruction::DynamicIdenticalNetDetection::add_if_not_contained( const whfc::Hyperedge he, const size_t he_hash, const vec& pins) { const size_t bucket_idx = he_hash % _hash_buckets.size(); if ( _hash_buckets[bucket_idx].threshold == _threshold ) { @@ -64,12 +64,12 @@ whfc::Hyperedge SequentialConstruction::DynamicIdenticalN return whfc::invalidHyperedge; } -template -FlowProblem SequentialConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem SequentialConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { FlowProblem flow_problem; const double density = static_cast(phg.initialNumEdges()) / phg.initialNumNodes(); const double avg_he_size = static_cast(phg.initialNumPins()) / phg.initialNumEdges(); @@ -109,13 +109,13 @@ FlowProblem SequentialConstruction::constructFlowHypergra return flow_problem; } -template -FlowProblem SequentialConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node, - const bool default_construction) { +template +FlowProblem SequentialConstruction::constructFlowHypergraph(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node, + const bool default_construction) { FlowProblem flow_problem; if ( default_construction ) { // This algorithm iterates over all hyperedges and checks for all pins if @@ -153,12 +153,12 @@ FlowProblem SequentialConstruction::constructFlowHypergra return flow_problem; } -template -FlowProblem SequentialConstruction::constructDefault(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem SequentialConstruction::constructDefault(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { ASSERT(block_0 != kInvalidPartition && block_1 != kInvalidPartition); FlowProblem flow_problem; flow_problem.total_cut = 0; @@ -274,12 +274,12 @@ FlowProblem SequentialConstruction::constructDefault(cons return flow_problem; } -template -FlowProblem SequentialConstruction::constructOptimizedForLargeHEs(const PartitionedHypergraph& phg, - const Subhypergraph& sub_hg, - const PartitionID block_0, - const PartitionID block_1, - vec& whfc_to_node) { +template +FlowProblem SequentialConstruction::constructOptimizedForLargeHEs(const PartitionedHypergraph& phg, + const Subhypergraph& sub_hg, + const PartitionID block_0, + const PartitionID block_1, + vec& whfc_to_node) { ASSERT(block_0 != kInvalidPartition && block_1 != kInvalidPartition); FlowProblem flow_problem; flow_problem.total_cut = 0; @@ -414,13 +414,13 @@ FlowProblem SequentialConstruction::constructOptimizedFor return flow_problem; } -template -void SequentialConstruction::determineDistanceFromCut(const PartitionedHypergraph& phg, - const whfc::Node source, - const whfc::Node sink, - const PartitionID block_0, - const PartitionID block_1, - const vec& whfc_to_node) { +template +void SequentialConstruction::determineDistanceFromCut(const PartitionedHypergraph& phg, + const whfc::Node source, + const whfc::Node sink, + const PartitionID block_0, + const PartitionID block_1, + const vec& whfc_to_node) { auto& distances = _hfc.cs.border_nodes.distance; distances.assign(_flow_hg.numNodes(), whfc::HopDistance(0)); _visited_hns.resize(_flow_hg.numNodes() + _flow_hg.numHyperedges()); @@ -478,9 +478,9 @@ void SequentialConstruction::determineDistanceFromCut(con } namespace { -#define SEQUENTIAL_CONSTRUCTION(X, Y) SequentialConstruction +#define SEQUENTIAL_CONSTRUCTION(X) SequentialConstruction } -INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(SEQUENTIAL_CONSTRUCTION) +INSTANTIATE_CLASS_WITH_VALID_TRAITS(SEQUENTIAL_CONSTRUCTION) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/flows/sequential_construction.h b/mt-kahypar/partition/refinement/flows/sequential_construction.h index fb6e79397..c686fc088 100644 --- a/mt-kahypar/partition/refinement/flows/sequential_construction.h +++ b/mt-kahypar/partition/refinement/flows/sequential_construction.h @@ -41,13 +41,13 @@ namespace mt_kahypar { struct FlowProblem; -template +template class SequentialConstruction { static constexpr bool debug = false; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using FlowNetworkConstruction = typename GainTypes::FlowNetworkConstruction; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using FlowNetworkConstruction = typename CombinedTraits::FlowNetworkConstruction; struct TmpPin { HyperedgeID e; diff --git a/mt-kahypar/partition/refinement/fm/fm_commons.cpp b/mt-kahypar/partition/refinement/fm/fm_commons.cpp index ca29e62e5..1050f687b 100644 --- a/mt-kahypar/partition/refinement/fm/fm_commons.cpp +++ b/mt-kahypar/partition/refinement/fm/fm_commons.cpp @@ -70,11 +70,11 @@ namespace mt_kahypar { } - template - void UnconstrainedFMData::InitializationHelper::initialize( + template + void UnconstrainedFMData::InitializationHelper::initialize( UnconstrainedFMData& data, const Context& context, - const typename TypeTraits::PartitionedHypergraph& phg, - const typename GainTypes::GainCache& gain_cache) { + const typename CombinedTraits::PartitionedHypergraph& phg, + const typename CombinedTraits::GainCache& gain_cache) { auto get_node_stats = [&](const HypernodeID hypernode) { // TODO(maas): we might want to save the total incident weight in the hypergraph data structure // at some point in the future @@ -250,8 +250,8 @@ namespace mt_kahypar { } namespace { - #define UNCONSTRAINED_FM_INITIALIZATION(X, Y) UnconstrainedFMData::InitializationHelper; + #define UNCONSTRAINED_FM_INITIALIZATION(X) UnconstrainedFMData::InitializationHelper } - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(UNCONSTRAINED_FM_INITIALIZATION) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(UNCONSTRAINED_FM_INITIALIZATION) } diff --git a/mt-kahypar/partition/refinement/fm/fm_commons.h b/mt-kahypar/partition/refinement/fm/fm_commons.h index ad153760b..fc600c504 100644 --- a/mt-kahypar/partition/refinement/fm/fm_commons.h +++ b/mt-kahypar/partition/refinement/fm/fm_commons.h @@ -155,11 +155,11 @@ class UnconstrainedFMData { using BucketID = uint32_t; using AtomicBucketID = parallel::IntegralAtomicWrapper; - template + template struct InitializationHelper { static void initialize(UnconstrainedFMData& data, const Context& context, - const typename TypeTraits::PartitionedHypergraph& phg, - const typename GainTypes::GainCache& gain_cache); + const typename CombinedTraits::PartitionedHypergraph& phg, + const typename CombinedTraits::GainCache& gain_cache); }; static constexpr BucketID NUM_BUCKETS = 16; @@ -175,14 +175,14 @@ class UnconstrainedFMData { local_bucket_weights(), rebalancing_nodes(num_nodes) { } - template + template void initialize(const Context& context, - const typename TypeTraits::PartitionedHypergraph& phg, - const typename GainTypes::GainCache& gain_cache) { + const typename CombinedTraits::PartitionedHypergraph& phg, + const typename CombinedTraits::GainCache& gain_cache) { changeNumberOfBlocks(context.partition.k); reset(); - InitializationHelper::initialize(*this, context, phg, gain_cache); + InitializationHelper::initialize(*this, context, phg, gain_cache); } Gain estimatePenaltyForImbalancedMove(PartitionID to, HypernodeWeight initial_imbalance, HypernodeWeight moved_weight) const; @@ -207,7 +207,7 @@ class UnconstrainedFMData { } private: - template + template friend class InitializationHelper; MT_KAHYPAR_ATTRIBUTE_ALWAYS_INLINE size_t indexForBucket(PartitionID block, BucketID bucketId) const { diff --git a/mt-kahypar/partition/refinement/fm/global_rollback.cpp b/mt-kahypar/partition/refinement/fm/global_rollback.cpp index ec7265a3d..67cdaca6d 100644 --- a/mt-kahypar/partition/refinement/fm/global_rollback.cpp +++ b/mt-kahypar/partition/refinement/fm/global_rollback.cpp @@ -155,8 +155,8 @@ namespace mt_kahypar { } }; - template - HyperedgeWeight GlobalRollback::revertToBestPrefixParallel( + template + HyperedgeWeight GlobalRollback::revertToBestPrefixParallel( PartitionedHypergraph& phg, FMSharedData& sharedData, const vec& partWeights, const std::vector& maxPartWeights) { const MoveID numMoves = sharedData.moveTracker.numPerformedMoves(); @@ -192,10 +192,10 @@ namespace mt_kahypar { return b.gain; } - template - void GlobalRollback::recalculateGainForHyperedge(PartitionedHypergraph& phg, - FMSharedData& sharedData, - const HyperedgeID& e) { + template + void GlobalRollback::recalculateGainForHyperedge(PartitionedHypergraph& phg, + FMSharedData& sharedData, + const HyperedgeID& e) { GlobalMoveTracker& tracker = sharedData.moveTracker; auto& r = ets_recalc_data.local(); @@ -250,10 +250,10 @@ namespace mt_kahypar { } } - template - void GlobalRollback::recalculateGainForHyperedgeViaAttributedGains(PartitionedHypergraph& phg, - FMSharedData& sharedData, - const HyperedgeID& e) { + template + void GlobalRollback::recalculateGainForHyperedgeViaAttributedGains(PartitionedHypergraph& phg, + FMSharedData& sharedData, + const HyperedgeID& e) { GlobalMoveTracker& tracker = sharedData.moveTracker; ds::Bitset& connectivity_set = phg.deepCopyOfConnectivitySet(e); ds::PinCountSnapshot pin_counts(phg.k(), phg.hypergraph().maxEdgeSize()); @@ -307,10 +307,10 @@ namespace mt_kahypar { } } - template - void GlobalRollback::recalculateGainForGraphEdgeViaAttributedGains(PartitionedHypergraph& phg, - FMSharedData& sharedData, - const HyperedgeID& e) { + template + void GlobalRollback::recalculateGainForGraphEdgeViaAttributedGains(PartitionedHypergraph& phg, + FMSharedData& sharedData, + const HyperedgeID& e) { if ( !phg.isSinglePin(e) ) { GlobalMoveTracker& tracker = sharedData.moveTracker; SynchronizedEdgeUpdate sync_update; @@ -371,9 +371,8 @@ namespace mt_kahypar { } } - template - void GlobalRollback::recalculateGains(PartitionedHypergraph& phg, - FMSharedData& sharedData) { + template + void GlobalRollback::recalculateGains(PartitionedHypergraph& phg, FMSharedData& sharedData) { GlobalMoveTracker& tracker = sharedData.moveTracker; auto recalculate_and_distribute_for_hyperedge = [&](const HyperedgeID e) { @@ -416,8 +415,8 @@ namespace mt_kahypar { } } - template - HyperedgeWeight GlobalRollback::revertToBestPrefixSequential( + template + HyperedgeWeight GlobalRollback::revertToBestPrefixSequential( PartitionedHypergraph& phg, FMSharedData& sharedData, const vec&, @@ -496,9 +495,8 @@ namespace mt_kahypar { } - template - bool GlobalRollback::verifyGains(PartitionedHypergraph& phg, - FMSharedData& sharedData) { + template + bool GlobalRollback::verifyGains(PartitionedHypergraph& phg, FMSharedData& sharedData) { vec& move_order = sharedData.moveTracker.moveOrder; auto recompute_penalty_terms = [&] { @@ -557,8 +555,8 @@ namespace mt_kahypar { } namespace { - #define GLOBAL_ROLLBACK(X, Y) GlobalRollback + #define GLOBAL_ROLLBACK(X) GlobalRollback } - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(GLOBAL_ROLLBACK) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(GLOBAL_ROLLBACK) } diff --git a/mt-kahypar/partition/refinement/fm/global_rollback.h b/mt-kahypar/partition/refinement/fm/global_rollback.h index 90c7470e3..a76448fa4 100644 --- a/mt-kahypar/partition/refinement/fm/global_rollback.h +++ b/mt-kahypar/partition/refinement/fm/global_rollback.h @@ -33,14 +33,14 @@ namespace mt_kahypar { -template +template class GlobalRollback { static constexpr bool enable_heavy_assert = false; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using AttributedGains = typename GainTypes::AttributedGains; - using Rollback = typename GainTypes::Rollback; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using AttributedGains = typename CombinedTraits::AttributedGains; + using Rollback = typename CombinedTraits::Rollback; using RecalculationData = typename Rollback::RecalculationData; public: diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp index e3c988bbc..aa37a2c18 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.cpp @@ -34,10 +34,10 @@ namespace mt_kahypar { - template + template template - bool LocalizedKWayFM::findMoves(DispatchedFMStrategy& fm_strategy, PartitionedHypergraph& phg, - size_t taskID, size_t numSeeds) { + bool LocalizedKWayFM::findMoves(DispatchedFMStrategy& fm_strategy, PartitionedHypergraph& phg, + size_t taskID, size_t numSeeds) { localMoves.clear(); thisSearch = ++sharedData.nodeTracker.highestActiveSearchID; @@ -73,11 +73,11 @@ namespace mt_kahypar { return std::make_pair(p, w); } - template + template template MT_KAHYPAR_ATTRIBUTE_ALWAYS_INLINE - void LocalizedKWayFM::acquireOrUpdateNeighbors(PHG& phg, CACHE& gain_cache, const Move& move, - DispatchedFMStrategy& fm_strategy) { + void LocalizedKWayFM::acquireOrUpdateNeighbors(PHG& phg, CACHE& gain_cache, const Move& move, + DispatchedFMStrategy& fm_strategy) { auto updateOrAcquire = [&](const HypernodeID v) { SearchID searchOfV = sharedData.nodeTracker.searchOfNode[v].load(std::memory_order_relaxed); if (searchOfV == thisSearch) { @@ -119,10 +119,10 @@ namespace mt_kahypar { } - template + template template - void LocalizedKWayFM::internalFindMoves(PartitionedHypergraph& phg, - DispatchedFMStrategy& fm_strategy) { + void LocalizedKWayFM::internalFindMoves(PartitionedHypergraph& phg, + DispatchedFMStrategy& fm_strategy) { StopRule stopRule(phg.initialNumNodes()); Move move; @@ -225,8 +225,8 @@ namespace mt_kahypar { } - template - void LocalizedKWayFM::changeNumberOfBlocks(const PartitionID new_k) { + template + void LocalizedKWayFM::changeNumberOfBlocks(const PartitionID new_k) { deltaPhg.changeNumberOfBlocks(new_k); blockPQ.resize(new_k); for ( VertexPriorityQueue& pq : vertexPQs ) { @@ -237,8 +237,8 @@ namespace mt_kahypar { } } - template - void LocalizedKWayFM::memoryConsumption(utils::MemoryTreeNode *parent) const { + template + void LocalizedKWayFM::memoryConsumption(utils::MemoryTreeNode *parent) const { ASSERT(parent); utils::MemoryTreeNode *localized_fm_node = parent->addChild("Localized k-Way FM"); @@ -262,13 +262,13 @@ namespace mt_kahypar { } namespace { - #define LOCALIZED_KWAY_FM(X, Y) LocalizedKWayFM; \ - template bool LocalizedKWayFM::findMoves(LocalUnconstrainedStrategy&, \ - typename LocalizedKWayFM::PartitionedHypergraph&, size_t, size_t); \ - template bool LocalizedKWayFM::findMoves(LocalGainCacheStrategy&, \ - typename LocalizedKWayFM::PartitionedHypergraph&, size_t, size_t) + #define LOCALIZED_KWAY_FM(X) LocalizedKWayFM; \ + template bool LocalizedKWayFM::findMoves(LocalUnconstrainedStrategy&, \ + typename LocalizedKWayFM::PartitionedHypergraph&, size_t, size_t); \ + template bool LocalizedKWayFM::findMoves(LocalGainCacheStrategy&, \ + typename LocalizedKWayFM::PartitionedHypergraph&, size_t, size_t) } - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(LOCALIZED_KWAY_FM) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(LOCALIZED_KWAY_FM) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h index a2747772b..2c0bccbe2 100644 --- a/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h +++ b/mt-kahypar/partition/refinement/fm/localized_kway_fm_core.h @@ -38,19 +38,19 @@ namespace mt_kahypar { -template +template class LocalizedKWayFM { public: - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; private: static constexpr size_t MAP_SIZE_LARGE = 16384; static constexpr size_t MAP_SIZE_MOVE_DELTA = 8192; - using GainCache = typename GainTypes::GainCache; - using DeltaGainCache = typename GainTypes::DeltaGainCache; + using GainCache = typename CombinedTraits::GainCache; + using DeltaGainCache = typename CombinedTraits::DeltaGainCache; using DeltaPartitionedHypergraph = typename PartitionedHypergraph::template DeltaPartition; - using AttributedGains = typename GainTypes::AttributedGains; + using AttributedGains = typename CombinedTraits::AttributedGains; using BlockPriorityQueue = ds::ExclusiveHandleHeap< ds::MaxHeap >; using VertexPriorityQueue = ds::MaxHeap; // these need external handles diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp index 267ced6d4..c809748b5 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.cpp @@ -40,12 +40,12 @@ namespace mt_kahypar { using ds::StreamingVector; - template - MultiTryKWayFM::MultiTryKWayFM(const HypernodeID num_hypernodes, - const HyperedgeID num_hyperedges, - const Context& c, - GainCache& gainCache, - IRebalancer& rb) : + template + MultiTryKWayFM::MultiTryKWayFM(const HypernodeID num_hypernodes, + const HyperedgeID num_hyperedges, + const Context& c, + GainCache& gainCache, + IRebalancer& rb) : initial_num_nodes(num_hypernodes), context(c), gain_cache(gainCache), @@ -77,12 +77,11 @@ namespace mt_kahypar { return max_part_weights; } - template - bool MultiTryKWayFM::refineImpl( - mt_kahypar_partitioned_hypergraph_t& hypergraph, - const vec& refinement_nodes, - Metrics& metrics, - const double time_limit) { + template + bool MultiTryKWayFM::refineImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, + const vec& refinement_nodes, + Metrics& metrics, + const double time_limit) { PartitionedHypergraph& phg = utils::cast(hypergraph); resizeDataStructuresForCurrentK(); @@ -109,7 +108,7 @@ namespace mt_kahypar { const bool is_unconstrained = fm_strategy->isUnconstrainedRound(round); if (is_unconstrained) { timer.start_timer("initialize_data_unconstrained", "Initialize Data for Unc. FM"); - sharedData.unconstrained.initialize(context, phg, gain_cache); + sharedData.unconstrained.initialize(context, phg, gain_cache); timer.stop_timer("initialize_data_unconstrained"); } @@ -226,8 +225,8 @@ namespace mt_kahypar { return overall_improvement > 0; } - template - void MultiTryKWayFM::roundInitialization(PartitionedHypergraph& phg, + template + void MultiTryKWayFM::roundInitialization(PartitionedHypergraph& phg, const vec& refinement_nodes) { // clear border nodes sharedData.refinementNodes.clear(); @@ -275,8 +274,8 @@ namespace mt_kahypar { sharedData.nodeTracker.requestNewSearches(static_cast(sharedData.refinementNodes.unsafe_size())); } - template - void MultiTryKWayFM::interleaveMoveSequenceWithRebalancingMoves( + template + void MultiTryKWayFM::interleaveMoveSequenceWithRebalancingMoves( const PartitionedHypergraph& phg, const vec& initialPartWeights, const std::vector& max_part_weights, @@ -384,8 +383,8 @@ namespace mt_kahypar { }, tbb::static_partitioner()); } - template - void MultiTryKWayFM::insertMovesToBalanceBlock(const PartitionedHypergraph& phg, + template + void MultiTryKWayFM::insertMovesToBalanceBlock(const PartitionedHypergraph& phg, const PartitionID block, const std::vector& max_part_weights, const vec>& rebalancing_moves_by_part, @@ -414,8 +413,8 @@ namespace mt_kahypar { } - template - void MultiTryKWayFM::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { + template + void MultiTryKWayFM::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { PartitionedHypergraph& phg = utils::cast(hypergraph); if (!gain_cache.isInitialized()) { @@ -423,8 +422,8 @@ namespace mt_kahypar { } } - template - void MultiTryKWayFM::resizeDataStructuresForCurrentK() { + template + void MultiTryKWayFM::resizeDataStructuresForCurrentK() { // If the number of blocks changes, we resize data structures // (can happen during deep multilevel partitioning) if ( current_k != context.partition.k ) { @@ -442,8 +441,8 @@ namespace mt_kahypar { } } - template - void MultiTryKWayFM::printMemoryConsumption() { + template + void MultiTryKWayFM::printMemoryConsumption() { utils::MemoryTreeNode fm_memory("Multitry k-Way FM", utils::OutputType::MEGABYTE); for (const auto& fm : ets_fm) { @@ -457,8 +456,8 @@ namespace mt_kahypar { } namespace { - #define MULTITRY_KWAY_FM(X, Y) MultiTryKWayFM + #define MULTITRY_KWAY_FM(X) MultiTryKWayFM } - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(MULTITRY_KWAY_FM) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(MULTITRY_KWAY_FM) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h index 6cf0ef357..077044c2c 100644 --- a/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h +++ b/mt-kahypar/partition/refinement/fm/multitry_kway_fm.h @@ -40,16 +40,16 @@ namespace mt_kahypar { -template +template class MultiTryKWayFM final : public IRefiner { static constexpr bool debug = false; static constexpr bool enable_heavy_assert = false; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using LocalizedFMSearch = LocalizedKWayFM; - using Rollback = GlobalRollback; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using LocalizedFMSearch = LocalizedKWayFM; + using Rollback = GlobalRollback; static_assert(GainCache::TYPE != GainPolicy::none); diff --git a/mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h b/mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h index c290252fb..0e6d2bdbe 100644 --- a/mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h +++ b/mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h @@ -33,13 +33,13 @@ namespace mt_kahypar { -template +template class GainCacheStrategy: public IFMStrategy { using Base = IFMStrategy; public: - using LocalFM = LocalizedKWayFM; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + using LocalFM = LocalizedKWayFM; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; GainCacheStrategy(const Context& context, FMSharedData& sharedData): Base(context, sharedData) { } diff --git a/mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h b/mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h index c4929734a..4ad2c2952 100644 --- a/mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h +++ b/mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h @@ -34,14 +34,14 @@ namespace mt_kahypar { -template +template class UnconstrainedStrategy: public IFMStrategy { using Base = IFMStrategy; static constexpr bool debug = false; public: - using LocalFM = LocalizedKWayFM; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + using LocalFM = LocalizedKWayFM; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; UnconstrainedStrategy(const Context& context, FMSharedData& sharedData): Base(context, sharedData), diff --git a/mt-kahypar/partition/refinement/gains/gain_definitions.h b/mt-kahypar/partition/refinement/gains/gain_definitions.h index 610fada88..69bdaed33 100644 --- a/mt-kahypar/partition/refinement/gains/gain_definitions.h +++ b/mt-kahypar/partition/refinement/gains/gain_definitions.h @@ -132,8 +132,11 @@ struct SteinerTreeForGraphsTypes : public kahypar::meta::PolicyBase { #endif #endif -template +template struct CombinedTraits : public kahypar::meta::PolicyBase { + using TypeTraits = TypeTraitsT; + using GainTypes = GainTypesT; + using Hypergraph = typename TypeTraits::Hypergraph; using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; @@ -189,15 +192,6 @@ using ValidTraitCombinations = kahypar::meta::Typelist<_LIST_HYPERGRAPH_COMBINAT ENABLE_LARGE_K(_INSTANTIATE_CLASS_MACRO_FOR_HYPERGRAPH_COMBINATIONS(C, LargeKHypergraphTypeTraits)) -#define INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(C) \ - INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, Km1GainTypes) \ - INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, CutGainTypes) \ - ENABLE_SOED(INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, SoedGainTypes)) \ - ENABLE_STEINER_TREE(INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, SteinerTreeGainTypes)) \ - ENABLE_GRAPHS(INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, CutGainForGraphsTypes)) \ - ENABLE_GRAPHS(ENABLE_STEINER_TREE(INSTANTIATE_CLASS_MACRO_WITH_TYPE_TRAITS_AND_OTHER_CLASS(C, SteinerTreeForGraphsTypes))) - - // functionality for retrieving combined policy of partition type and gain #define _RETURN_COMBINED_POLICY(TYPE_TRAITS, GAIN_TYPES) { \ static CombinedTraits traits; \ diff --git a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp index b86fc3e1f..6b9b1af46 100644 --- a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp +++ b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.cpp @@ -39,12 +39,12 @@ namespace mt_kahypar { - template + template template - bool LabelPropagationRefiner::moveVertex(PartitionedHypergraph& hypergraph, - const HypernodeID hn, - NextActiveNodes& next_active_nodes, - const F& objective_delta) { + bool LabelPropagationRefiner::moveVertex(PartitionedHypergraph& hypergraph, + const HypernodeID hn, + NextActiveNodes& next_active_nodes, + const F& objective_delta) { bool is_moved = false; ASSERT(hn != kInvalidHypernode); if ( hypergraph.isBorderNode(hn) && !hypergraph.isFixed(hn) ) { @@ -98,12 +98,11 @@ namespace mt_kahypar { return is_moved; } - template - bool LabelPropagationRefiner::refineImpl( - mt_kahypar_partitioned_hypergraph_t& phg, - const parallel::scalable_vector& refinement_nodes, - Metrics& best_metrics, - const double) { + template + bool LabelPropagationRefiner::refineImpl(mt_kahypar_partitioned_hypergraph_t& phg, + const vec& refinement_nodes, + Metrics& best_metrics, + const double) { PartitionedHypergraph& hypergraph = utils::cast(phg); resizeDataStructuresForCurrentK(); _gain.reset(); @@ -131,9 +130,9 @@ namespace mt_kahypar { } - template - void LabelPropagationRefiner::labelPropagation(PartitionedHypergraph& hypergraph, - Metrics& best_metrics) { + template + void LabelPropagationRefiner::labelPropagation(PartitionedHypergraph& hypergraph, + Metrics& best_metrics) { NextActiveNodes next_active_nodes; vec rebalance_moves; bool should_stop = false; @@ -151,13 +150,12 @@ namespace mt_kahypar { } } - template - bool LabelPropagationRefiner::labelPropagationRound( - PartitionedHypergraph& hypergraph, - NextActiveNodes& next_active_nodes, - Metrics& best_metrics, - vec& rebalance_moves, - bool unconstrained_lp) { + template + bool LabelPropagationRefiner::labelPropagationRound(PartitionedHypergraph& hypergraph, + NextActiveNodes& next_active_nodes, + Metrics& best_metrics, + vec& rebalance_moves, + bool unconstrained_lp) { Metrics current_metrics = best_metrics; _visited_he.reset(); _next_active.reset(); @@ -217,10 +215,10 @@ namespace mt_kahypar { _context.refinement.label_propagation.relative_improvement_threshold * old_quality; } - template + template template - void LabelPropagationRefiner::moveActiveNodes(PartitionedHypergraph& phg, - NextActiveNodes& next_active_nodes) { + void LabelPropagationRefiner::moveActiveNodes(PartitionedHypergraph& phg, + NextActiveNodes& next_active_nodes) { // This function is passed as lambda to the changeNodePart function and used // to calculate the "real" delta of a move (in terms of the used objective function). auto objective_delta = [&](const SynchronizedEdgeUpdate& sync_update) { @@ -253,11 +251,11 @@ namespace mt_kahypar { } - template - bool LabelPropagationRefiner::applyRebalancing(PartitionedHypergraph& hypergraph, - Metrics& best_metrics, - Metrics& current_metrics, - vec& rebalance_moves) { + template + bool LabelPropagationRefiner::applyRebalancing(PartitionedHypergraph& hypergraph, + Metrics& best_metrics, + Metrics& current_metrics, + vec& rebalance_moves) { utils::Timer& timer = utils::Utilities::instance().getTimer(_context.utility_id); timer.start_timer("rebalance_lp", "Rebalance"); mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(hypergraph); @@ -296,9 +294,9 @@ namespace mt_kahypar { return false; } - template + template template - void LabelPropagationRefiner::forEachMovedNode(F node_fn) { + void LabelPropagationRefiner::forEachMovedNode(F node_fn) { if ( _context.refinement.label_propagation.execute_sequential ) { for (size_t j = 0; j < _active_nodes.size(); j++) { if (_active_node_was_moved[j]) { @@ -314,15 +312,14 @@ namespace mt_kahypar { } } - template - void LabelPropagationRefiner::initializeImpl(mt_kahypar_partitioned_hypergraph_t& phg) { + template + void LabelPropagationRefiner::initializeImpl(mt_kahypar_partitioned_hypergraph_t& phg) { unused(phg); } - template - void LabelPropagationRefiner::initializeActiveNodes( - PartitionedHypergraph& hypergraph, - const parallel::scalable_vector& refinement_nodes) { + template + void LabelPropagationRefiner::initializeActiveNodes(PartitionedHypergraph& hypergraph, + const vec& refinement_nodes) { _active_nodes.clear(); if ( refinement_nodes.empty() ) { _might_be_uninitialized = false; @@ -379,9 +376,9 @@ namespace mt_kahypar { } namespace { - #define LABEL_PROPAGATION_REFINER(X, Y) LabelPropagationRefiner + #define LABEL_PROPAGATION_REFINER(X) LabelPropagationRefiner } // explicitly instantiate so the compiler can generate them when compiling this cpp file - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(LABEL_PROPAGATION_REFINER) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(LABEL_PROPAGATION_REFINER) } diff --git a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h index 52e90c9d1..bbf0ece2f 100644 --- a/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h +++ b/mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h @@ -40,13 +40,13 @@ namespace mt_kahypar { -template +template class LabelPropagationRefiner final : public IRefiner { private: - using Hypergraph = typename TypeTraits::Hypergraph; - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using GainCalculator = typename GainTypes::GainComputation; + using Hypergraph = typename CombinedTraits::Hypergraph; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using GainCalculator = typename CombinedTraits::GainComputation; using ActiveNodes = parallel::scalable_vector; using NextActiveNodes = ds::StreamingVector; diff --git a/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.cpp b/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.cpp index 9366dff86..b07935faf 100644 --- a/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.cpp +++ b/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.cpp @@ -254,8 +254,8 @@ namespace impl { } // namespace impl - template - void AdvancedRebalancer::insertNodesInOverloadedBlocks(mt_kahypar_partitioned_hypergraph_t& hypergraph) { + template + void AdvancedRebalancer::insertNodesInOverloadedBlocks(mt_kahypar_partitioned_hypergraph_t& hypergraph) { auto& phg = utils::cast(hypergraph); // init PQs if not done before @@ -305,8 +305,8 @@ namespace impl { } } - template - std::pair AdvancedRebalancer::findMoves(mt_kahypar_partitioned_hypergraph_t& hypergraph) { + template + std::pair AdvancedRebalancer::findMoves(mt_kahypar_partitioned_hypergraph_t& hypergraph) { auto& phg = utils::cast(hypergraph); int64_t attributed_gain = 0; size_t global_move_id = 0; @@ -417,11 +417,11 @@ namespace impl { return std::make_pair(attributed_gain, global_move_id); } - template - bool AdvancedRebalancer::refineInternalParallel(mt_kahypar_partitioned_hypergraph_t& hypergraph, - vec>* moves_by_part, - vec* moves_linear, - Metrics& best_metric) { + template + bool AdvancedRebalancer::refineInternalParallel(mt_kahypar_partitioned_hypergraph_t& hypergraph, + vec>* moves_by_part, + vec* moves_linear, + Metrics& best_metric) { auto& phg = utils::cast(hypergraph); if (!_gain_cache.isInitialized()) { @@ -477,8 +477,8 @@ namespace impl { } -template -AdvancedRebalancer::AdvancedRebalancer( +template +AdvancedRebalancer::AdvancedRebalancer( HypernodeID num_nodes, const Context& context, GainCache& gain_cache) : _context(context), _gain_cache(gain_cache), @@ -490,48 +490,48 @@ AdvancedRebalancer::AdvancedRebalancer( _pq_id(num_nodes, -1), _node_state(num_nodes) { } -template -AdvancedRebalancer::AdvancedRebalancer( +template +AdvancedRebalancer::AdvancedRebalancer( HypernodeID num_nodes, const Context& context, gain_cache_t gain_cache) : AdvancedRebalancer(num_nodes, context, GainCachePtr::cast(gain_cache)) { } -template -bool AdvancedRebalancer::refineImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, +template +bool AdvancedRebalancer::refineImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, const vec& , Metrics& best_metrics, double) { return refineInternalParallel(hypergraph, nullptr, nullptr, best_metrics); } -template -void AdvancedRebalancer::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { +template +void AdvancedRebalancer::initializeImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph) { auto& phg = utils::cast(hypergraph); unused(phg); } -template -bool AdvancedRebalancer::refineAndOutputMovesImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, - const vec& , - vec>& moves_by_part, - Metrics& best_metrics, - const double) { +template +bool AdvancedRebalancer::refineAndOutputMovesImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, + const vec& , + vec>& moves_by_part, + Metrics& best_metrics, + const double) { return refineInternalParallel(hypergraph, &moves_by_part, nullptr, best_metrics); } -template -bool AdvancedRebalancer::refineAndOutputMovesLinearImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, - const vec& , - vec& moves, - Metrics& best_metrics, - const double) { +template +bool AdvancedRebalancer::refineAndOutputMovesLinearImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, + const vec& , + vec& moves, + Metrics& best_metrics, + const double) { return refineInternalParallel(hypergraph, nullptr, &moves, best_metrics); } // explicitly instantiate so the compiler can generate them when compiling this cpp file namespace { - #define ADVANCED_REBALANCER(X, Y) AdvancedRebalancer + #define ADVANCED_REBALANCER(X) AdvancedRebalancer } // explicitly instantiate so the compiler can generate them when compiling this cpp file -INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(ADVANCED_REBALANCER) +INSTANTIATE_CLASS_WITH_VALID_TRAITS(ADVANCED_REBALANCER) } // namespace mt_kahypar diff --git a/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h b/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h index 39979f641..a7cb8de58 100644 --- a/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h +++ b/mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h @@ -74,13 +74,13 @@ namespace rebalancer { } // namespace rebalancer -template +template class AdvancedRebalancer final : public IRebalancer { private: - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using GainCalculator = typename GainTypes::GainComputation; - using AttributedGains = typename GainTypes::AttributedGains; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using GainCalculator = typename CombinedTraits::GainComputation; + using AttributedGains = typename CombinedTraits::AttributedGains; static constexpr bool debug = false; static constexpr bool enable_heavy_assert = false; diff --git a/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.cpp b/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.cpp index 7bb9b2a09..9fd3a41cd 100644 --- a/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.cpp +++ b/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.cpp @@ -42,11 +42,11 @@ namespace mt_kahypar { - template - bool SimpleRebalancer::refineImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, - const vec&, - Metrics& best_metrics, - double) { + template + bool SimpleRebalancer::refineImpl(mt_kahypar_partitioned_hypergraph_t& hypergraph, + const vec&, + Metrics& best_metrics, + double) { PartitionedHypergraph& phg = utils::cast(hypergraph); resizeDataStructuresForCurrentK(); // If partition is imbalanced, rebalancer is activated @@ -185,8 +185,8 @@ namespace mt_kahypar { return improvement; } - template - vec SimpleRebalancer::repairEmptyBlocks(PartitionedHypergraph& phg) { + template + vec SimpleRebalancer::repairEmptyBlocks(PartitionedHypergraph& phg) { // First detect if there are any empty blocks. const size_t k = size_t(_context.partition.k); boost::dynamic_bitset<> is_empty(k); @@ -291,9 +291,9 @@ namespace mt_kahypar { // explicitly instantiate so the compiler can generate them when compiling this cpp file namespace { - #define SIMPLE_REBALANCER(X, Y) SimpleRebalancer + #define SIMPLE_REBALANCER(X) SimpleRebalancer } // explicitly instantiate so the compiler can generate them when compiling this cpp file - INSTANTIATE_CLASS_WITH_TYPE_TRAITS_AND_GAIN_TYPES(SIMPLE_REBALANCER) + INSTANTIATE_CLASS_WITH_VALID_TRAITS(SIMPLE_REBALANCER) } diff --git a/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h b/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h index 20d3b497a..17f257e3f 100644 --- a/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h +++ b/mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h @@ -39,12 +39,12 @@ #include "mt-kahypar/utils/cast.h" namespace mt_kahypar { -template +template class SimpleRebalancer final : public IRebalancer { private: - using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using GainCache = typename GainTypes::GainCache; - using GainCalculator = typename GainTypes::GainComputation; + using PartitionedHypergraph = typename CombinedTraits::PartitionedHypergraph; + using GainCache = typename CombinedTraits::GainCache; + using GainCalculator = typename CombinedTraits::GainComputation; using AtomicWeight = parallel::IntegralAtomicWrapper; static constexpr bool debug = false; diff --git a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp index f0c707e6e..c2d02ff0a 100644 --- a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp +++ b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp @@ -152,10 +152,7 @@ kahypar::meta::PolicyBase& getCombinedTraitsPolicy(mt_kahypar_partition_type_t p REGISTER_DISPATCHED_LP_REFINER(LabelPropagationAlgorithm::label_propagation, LabelPropagationDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_DISPATCHED_LP_REFINER(LabelPropagationAlgorithm::deterministic, DeterministicLabelPropagationDispatcher, kahypar::meta::PolicyRegistry::getInstance().getPolicy( @@ -164,58 +161,34 @@ REGISTER_LP_REFINER(LabelPropagationAlgorithm::do_nothing, DoNothingRefiner, 1); REGISTER_DISPATCHED_FM_REFINER(FMAlgorithm::kway_fm, DefaultFMDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_DISPATCHED_FM_REFINER(FMAlgorithm::unconstrained_fm, UnconstrainedFMDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_FM_REFINER(FMAlgorithm::do_nothing, DoNothingRefiner, 3); REGISTER_DISPATCHED_FM_STRATEGY(FMAlgorithm::kway_fm, GainCacheFMStrategyDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_DISPATCHED_FM_STRATEGY(FMAlgorithm::unconstrained_fm, UnconstrainedFMStrategyDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_DISPATCHED_FLOW_SCHEDULER(FlowAlgorithm::flow_cutter, FlowSchedulerDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_FLOW_SCHEDULER(FlowAlgorithm::do_nothing, DoNothingRefiner, 4); REGISTER_DISPATCHED_REBALANCER(RebalancingAlgorithm::simple_rebalancer, SimpleRebalancerDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_DISPATCHED_REBALANCER(RebalancingAlgorithm::advanced_rebalancer, - AdvancedRebalancerDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + AdvancedRebalancerDispatcher, + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_REBALANCER(RebalancingAlgorithm::do_nothing, DoNothingRefiner, 5); REGISTER_DISPATCHED_FLOW_REFINER(FlowAlgorithm::flow_cutter, - FlowRefinementDispatcher, - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.partition_type), - kahypar::meta::PolicyRegistry::getInstance().getPolicy( - context.partition.gain_policy)); + FlowRefinementDispatcher, + getCombinedTraitsPolicy(context.partition.partition_type, context.partition.gain_policy)); REGISTER_FLOW_REFINER(FlowAlgorithm::do_nothing, DoNothingFlowRefiner, 6); } // namespace mt_kahypar diff --git a/tests/partition/refinement/advanced_rebalancer_test.cc b/tests/partition/refinement/advanced_rebalancer_test.cc index c211882a6..cae8988b4 100644 --- a/tests/partition/refinement/advanced_rebalancer_test.cc +++ b/tests/partition/refinement/advanced_rebalancer_test.cc @@ -57,7 +57,7 @@ class RebalancerTest : public Test { using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; using HypergraphFactory = typename Hypergraph::Factory; using GainCache = typename GainTypes::GainCache; - using Km1Rebalancer = AdvancedRebalancer; + using Rebalancer = AdvancedRebalancer>; RebalancerTest() : hypergraph(), @@ -102,7 +102,7 @@ class RebalancerTest : public Test { partitioned_hypergraph = PartitionedHypergraph(context.partition.k, hypergraph, parallel_tag_t()); context.setupPartWeights(hypergraph.totalWeight()); - rebalancer = std::make_unique(hypergraph.initialNumNodes(), context, gain_cache); + rebalancer = std::make_unique(hypergraph.initialNumNodes(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(partitioned_hypergraph); rebalancer->initialize(phg); } @@ -111,7 +111,7 @@ class RebalancerTest : public Test { PartitionedHypergraph partitioned_hypergraph; Context context; GainCache gain_cache; - std::unique_ptr rebalancer; + std::unique_ptr rebalancer; }; diff --git a/tests/partition/refinement/flow_construction_test.cc b/tests/partition/refinement/flow_construction_test.cc index 0ca3ba45a..a83116e61 100644 --- a/tests/partition/refinement/flow_construction_test.cc +++ b/tests/partition/refinement/flow_construction_test.cc @@ -113,10 +113,10 @@ class AFlowHypergraphConstructor : public Test { vec whfc_to_node; }; -typedef ::testing::Types, whfc::SequentialPushRelabel, true>, - Config, whfc::SequentialPushRelabel, false>, - Config, whfc::ParallelPushRelabel, true>, - Config, whfc::ParallelPushRelabel, false> > TestConfigs; +typedef ::testing::Types>, whfc::SequentialPushRelabel, true>, + Config>, whfc::SequentialPushRelabel, false>, + Config>, whfc::ParallelPushRelabel, true>, + Config>, whfc::ParallelPushRelabel, false> > TestConfigs; TYPED_TEST_CASE(AFlowHypergraphConstructor, TestConfigs); diff --git a/tests/partition/refinement/label_propagation_refiner_test.cc b/tests/partition/refinement/label_propagation_refiner_test.cc index 5c04ed648..d848757c9 100644 --- a/tests/partition/refinement/label_propagation_refiner_test.cc +++ b/tests/partition/refinement/label_propagation_refiner_test.cc @@ -46,7 +46,7 @@ template struct TestConfig { using TypeTraits = TypeTraitsT; using GainTypes = Km1GainTypes; - using Refiner = LabelPropagationRefiner; + using Refiner = LabelPropagationRefiner>; static constexpr PartitionID K = k; static constexpr Objective OBJECTIVE = Objective::km1; static constexpr LabelPropagationAlgorithm LP_ALGO = LabelPropagationAlgorithm::label_propagation; @@ -57,7 +57,7 @@ template struct TestConfig { using TypeTraits = TypeTraitsT; using GainTypes = CutGainTypes; - using Refiner = LabelPropagationRefiner; + using Refiner = LabelPropagationRefiner>; static constexpr PartitionID K = k; static constexpr Objective OBJECTIVE = Objective::cut; static constexpr LabelPropagationAlgorithm LP_ALGO = LabelPropagationAlgorithm::label_propagation; @@ -122,7 +122,8 @@ class ALabelPropagationRefiner : public Test { context.setupPartWeights(hypergraph.totalWeight()); initialPartition(); - rebalancer = std::make_unique>(hypergraph.initialNumNodes(), context, gain_cache); + rebalancer = std::make_unique>>( + hypergraph.initialNumNodes(), context, gain_cache); refiner = std::make_unique( hypergraph.initialNumNodes(), hypergraph.initialNumEdges(), context, gain_cache, *rebalancer); mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(partitioned_hypergraph); diff --git a/tests/partition/refinement/multitry_fm_test.cc b/tests/partition/refinement/multitry_fm_test.cc index 4fc0205e1..724477462 100644 --- a/tests/partition/refinement/multitry_fm_test.cc +++ b/tests/partition/refinement/multitry_fm_test.cc @@ -54,7 +54,7 @@ class MultiTryFMTest : public Test { using TypeTraits = typename Config::TypeTraits; using Hypergraph = typename TypeTraits::Hypergraph; using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using Refiner = MultiTryKWayFM; + using Refiner = MultiTryKWayFM>; MultiTryFMTest() : hypergraph(), @@ -108,7 +108,8 @@ class MultiTryFMTest : public Test { context.setupPartWeights(hypergraph.totalWeight()); initialPartition(); - rebalancer = std::make_unique>(hypergraph.initialNumNodes(), context, gain_cache); + rebalancer = std::make_unique>>( + hypergraph.initialNumNodes(), context, gain_cache); refiner = std::make_unique(hypergraph.initialNumNodes(), hypergraph.initialNumEdges(), context, gain_cache, *rebalancer); mt_kahypar_partitioned_hypergraph_t phg = utils::partitioned_hg_cast(partitioned_hypergraph); @@ -274,7 +275,7 @@ TEST(UnconstrainedFMDataTest, CorrectlyComputesPenalty) { gain_cache.initializeGainCache(phg); UnconstrainedFMData ufm_data(4); - ufm_data.initialize(context, phg, gain_cache); + ufm_data.initialize>(context, phg, gain_cache); ASSERT_EQ(0, ufm_data.estimatePenaltyForImbalancedMove(0, -1, -1)); ASSERT_LE(1.0, ufm_data.estimatePenaltyForImbalancedMove(0, 0, 1)); diff --git a/tests/partition/refinement/rebalance_test.cc b/tests/partition/refinement/rebalance_test.cc index 7d4032671..aa68e252b 100644 --- a/tests/partition/refinement/rebalance_test.cc +++ b/tests/partition/refinement/rebalance_test.cc @@ -43,7 +43,7 @@ namespace { using TypeTraits = StaticHypergraphTypeTraits; using Hypergraph = typename TypeTraits::Hypergraph; using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; - using Km1Rebalancer = SimpleRebalancer; + using Km1Rebalancer = SimpleRebalancer>; } diff --git a/tests/partition/refinement/rollback_test.cc b/tests/partition/refinement/rollback_test.cc index c7edab07b..1a19d98bb 100644 --- a/tests/partition/refinement/rollback_test.cc +++ b/tests/partition/refinement/rollback_test.cc @@ -79,7 +79,7 @@ TEST(RollbackTests, GainRecalculationAndRollsbackCorrectly) { FMSharedData sharedData(hg.initialNumNodes(), false); - GlobalRollback grb( + GlobalRollback> grb( hg.initialNumEdges(), context, gain_cache); auto performMove = [&](Move m) { if (phg.changeNodePart(gain_cache, m.node, m.from, m.to)) { @@ -136,7 +136,7 @@ TEST(RollbackTests, GainRecalculation2) { FMSharedData sharedData(hg.initialNumNodes(), false); - GlobalRollback grb( + GlobalRollback> grb( hg.initialNumEdges(), context, gain_cache); auto performUpdates = [&](Move& m) { diff --git a/tests/partition/refinement/scheduler_test.cc b/tests/partition/refinement/scheduler_test.cc index 511d44682..9bc6d4dc7 100644 --- a/tests/partition/refinement/scheduler_test.cc +++ b/tests/partition/refinement/scheduler_test.cc @@ -104,7 +104,7 @@ void verifyPartWeights(const vec actual_weights, TEST_F(AFlowRefinementScheduler, MovesOneVertex) { Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -120,7 +120,7 @@ TEST_F(AFlowRefinementScheduler, MovesOneVertex) { TEST_F(AFlowRefinementScheduler, MovesVerticesWithIntermediateBalanceViolation) { Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -138,7 +138,7 @@ TEST_F(AFlowRefinementScheduler, MovesVerticesWithIntermediateBalanceViolation) TEST_F(AFlowRefinementScheduler, MovesAVertexThatWorsenSolutionQuality) { Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -154,7 +154,7 @@ TEST_F(AFlowRefinementScheduler, MovesAVertexThatWorsenSolutionQuality) { TEST_F(AFlowRefinementScheduler, MovesAVertexThatViolatesBalanceConstraint) { Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -171,7 +171,7 @@ TEST_F(AFlowRefinementScheduler, MovesAVertexThatViolatesBalanceConstraint) { TEST_F(AFlowRefinementScheduler, MovesTwoVerticesConcurrently) { context.partition.max_part_weights.assign(2, 5); Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -198,7 +198,7 @@ TEST_F(AFlowRefinementScheduler, MovesTwoVerticesConcurrently) { TEST_F(AFlowRefinementScheduler, MovesTwoVerticesConcurrentlyWhereOneViolateBalanceConstraint) { Km1GainCache gain_cache; - FlowRefinementScheduler refiner( + FlowRefinementScheduler> refiner( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); mt_kahypar_partitioned_hypergraph_t partitioned_hg = utils::partitioned_hg_cast(phg); refiner.initialize(partitioned_hg); @@ -320,7 +320,7 @@ class AFlowRefinementEndToEnd : public Test { TEST_F(AFlowRefinementEndToEnd, SmokeTestWithTwoBlocksPerRefiner) { const bool debug = false; Km1GainCache gain_cache; - FlowRefinementScheduler scheduler( + FlowRefinementScheduler> scheduler( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); Metrics metrics; @@ -356,7 +356,7 @@ TEST_F(AFlowRefinementEndToEnd, SmokeTestWithFourBlocksPerRefiner) { const bool debug = false; FlowRefinerMockControl::instance().max_num_blocks = 4; Km1GainCache gain_cache; - FlowRefinementScheduler scheduler( + FlowRefinementScheduler> scheduler( hg.initialNumNodes(), hg.initialNumEdges(), context, gain_cache); Metrics metrics; From 64b8b59d7207cab33b9a1f0e4653cdd60701526e Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 14 Sep 2023 11:15:35 +0200 Subject: [PATCH 12/18] [compile time] move refinement/coarsening dispatchers to cpp files marginal improvement at best --- .../partition/coarsening/nlevel_uncoarsener.h | 1 + mt-kahypar/partition/factories.h | 87 +------------------ .../register_coarsening_algorithms.cpp | 32 ++++++- .../register_refinement_algorithms.cpp | 64 +++++++++++++- 4 files changed, 96 insertions(+), 88 deletions(-) diff --git a/mt-kahypar/partition/coarsening/nlevel_uncoarsener.h b/mt-kahypar/partition/coarsening/nlevel_uncoarsener.h index 2f3512d70..2aee0dad8 100644 --- a/mt-kahypar/partition/coarsening/nlevel_uncoarsener.h +++ b/mt-kahypar/partition/coarsening/nlevel_uncoarsener.h @@ -36,6 +36,7 @@ #include "mt-kahypar/partition/refinement/i_refiner.h" #include "mt-kahypar/partition/coarsening/coarsening_commons.h" #include "mt-kahypar/datastructures/streaming_vector.h" +#include "mt-kahypar/utils/progress_bar.h" namespace mt_kahypar { diff --git a/mt-kahypar/partition/factories.h b/mt-kahypar/partition/factories.h index 9de7b9d4d..11a551da7 100644 --- a/mt-kahypar/partition/factories.h +++ b/mt-kahypar/partition/factories.h @@ -28,120 +28,35 @@ #pragma once #include "kahypar-resources/meta/abstract_factory.h" -#include "kahypar-resources/meta/static_multi_dispatch_factory.h" -#include "kahypar-resources/meta/typelist.h" #include "mt-kahypar/definitions.h" -#ifdef KAHYPAR_ENABLE_HIGHEST_QUALITY_FEATURES -#include "mt-kahypar/partition/coarsening/nlevel_coarsener.h" -#endif -#include "mt-kahypar/partition/coarsening/multilevel_coarsener.h" -#include "mt-kahypar/partition/coarsening/deterministic_multilevel_coarsener.h" #include "mt-kahypar/partition/coarsening/i_coarsener.h" -#include "mt-kahypar/partition/coarsening/policies/rating_acceptance_policy.h" -#include "mt-kahypar/partition/coarsening/policies/rating_heavy_node_penalty_policy.h" #include "mt-kahypar/partition/context.h" #include "mt-kahypar/partition/refinement/i_refiner.h" #include "mt-kahypar/partition/refinement/i_rebalancer.h" #include "mt-kahypar/partition/refinement/flows/i_flow_refiner.h" -#include "mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h" -#include "mt-kahypar/partition/refinement/deterministic/deterministic_label_propagation.h" #include "mt-kahypar/partition/refinement/fm/fm_commons.h" -#include "mt-kahypar/partition/refinement/fm/multitry_kway_fm.h" #include "mt-kahypar/partition/refinement/fm/strategies/i_fm_strategy.h" -#include "mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h" -#include "mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h" -#include "mt-kahypar/partition/refinement/gains/gain_definitions.h" -#include "mt-kahypar/partition/refinement/flows/scheduler.h" -#include "mt-kahypar/partition/refinement/flows/flow_refiner.h" -#include "mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h" -#include "mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h" +#include "mt-kahypar/partition/refinement/gains/gain_cache_ptr.h" namespace mt_kahypar { using CoarsenerFactory = kahypar::meta::Factory; -using MultilevelCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory >; - -using DeterministicCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory>; - -#ifdef KAHYPAR_ENABLE_HIGHEST_QUALITY_FEATURES -using NLevelCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory >; -#endif - using LabelPropagationFactory = kahypar::meta::Factory; -using LabelPropagationDispatcher = kahypar::meta::StaticMultiDispatchFactory< - LabelPropagationRefiner, - IRefiner, - kahypar::meta::Typelist>; - -using DeterministicLabelPropagationDispatcher = kahypar::meta::StaticMultiDispatchFactory< - DeterministicLabelPropagationRefiner, - IRefiner, - kahypar::meta::Typelist>; - using FMFactory = kahypar::meta::Factory; -using DefaultFMDispatcher = kahypar::meta::StaticMultiDispatchFactory< - MultiTryKWayFM, - IRefiner, - kahypar::meta::Typelist>; - -using UnconstrainedFMDispatcher = DefaultFMDispatcher; - using FMStrategyFactory = kahypar::meta::Factory; -using GainCacheFMStrategyDispatcher = kahypar::meta::StaticMultiDispatchFactory< - GainCacheStrategy, - IFMStrategy, - kahypar::meta::Typelist>; - -using UnconstrainedFMStrategyDispatcher = kahypar::meta::StaticMultiDispatchFactory< - UnconstrainedStrategy, - IFMStrategy, - kahypar::meta::Typelist>; - using FlowSchedulerFactory = kahypar::meta::Factory; -using FlowSchedulerDispatcher = kahypar::meta::StaticMultiDispatchFactory< - FlowRefinementScheduler, - IRefiner, - kahypar::meta::Typelist>; - using RebalancerFactory = kahypar::meta::Factory; -using SimpleRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< - SimpleRebalancer, - IRebalancer, - kahypar::meta::Typelist>; - -using AdvancedRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< - AdvancedRebalancer, - IRebalancer, - kahypar::meta::Typelist>; - using FlowRefinementFactory = kahypar::meta::Factory; - -using FlowRefinementDispatcher = kahypar::meta::StaticMultiDispatchFactory< - FlowRefiner, - IFlowRefiner, - kahypar::meta::Typelist>; } // namespace mt_kahypar diff --git a/mt-kahypar/partition/registries/register_coarsening_algorithms.cpp b/mt-kahypar/partition/registries/register_coarsening_algorithms.cpp index 964713c52..9f7e93f07 100644 --- a/mt-kahypar/partition/registries/register_coarsening_algorithms.cpp +++ b/mt-kahypar/partition/registries/register_coarsening_algorithms.cpp @@ -26,11 +26,42 @@ ******************************************************************************/ #include "kahypar-resources/meta/registrar.h" +#include "kahypar-resources/meta/static_multi_dispatch_factory.h" +#include "kahypar-resources/meta/typelist.h" +#include "mt-kahypar/definitions.h" +#ifdef KAHYPAR_ENABLE_HIGHEST_QUALITY_FEATURES +#include "mt-kahypar/partition/coarsening/nlevel_coarsener.h" +#endif +#include "mt-kahypar/partition/coarsening/multilevel_coarsener.h" +#include "mt-kahypar/partition/coarsening/deterministic_multilevel_coarsener.h" +#include "mt-kahypar/partition/coarsening/policies/rating_acceptance_policy.h" +#include "mt-kahypar/partition/coarsening/policies/rating_heavy_node_penalty_policy.h" #include "mt-kahypar/partition/context.h" #include "mt-kahypar/partition/factories.h" +namespace mt_kahypar { +using MultilevelCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory >; + +using DeterministicCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory>; + +#ifdef KAHYPAR_ENABLE_HIGHEST_QUALITY_FEATURES +using NLevelCoarsenerDispatcher = kahypar::meta::StaticMultiDispatchFactory >; +#endif + #define REGISTER_DISPATCHED_COARSENER(id, dispatcher, ...) \ static kahypar::meta::Registrar register_ ## dispatcher( \ @@ -43,7 +74,6 @@ }) -namespace mt_kahypar { REGISTER_DISPATCHED_COARSENER(CoarseningAlgorithm::multilevel_coarsener, MultilevelCoarsenerDispatcher, kahypar::meta::PolicyRegistry::getInstance().getPolicy( diff --git a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp index c2d02ff0a..94d9f504f 100644 --- a/mt-kahypar/partition/registries/register_refinement_algorithms.cpp +++ b/mt-kahypar/partition/registries/register_refinement_algorithms.cpp @@ -26,12 +26,74 @@ ******************************************************************************/ #include "kahypar-resources/meta/registrar.h" +#include "kahypar-resources/meta/static_multi_dispatch_factory.h" +#include "kahypar-resources/meta/typelist.h" +#include "mt-kahypar/definitions.h" #include "mt-kahypar/partition/context.h" #include "mt-kahypar/partition/factories.h" #include "mt-kahypar/partition/refinement/do_nothing_refiner.h" +#include "mt-kahypar/partition/refinement/label_propagation/label_propagation_refiner.h" +#include "mt-kahypar/partition/refinement/deterministic/deterministic_label_propagation.h" +#include "mt-kahypar/partition/refinement/fm/multitry_kway_fm.h" +#include "mt-kahypar/partition/refinement/fm/strategies/gain_cache_strategy.h" +#include "mt-kahypar/partition/refinement/fm/strategies/unconstrained_strategy.h" #include "mt-kahypar/partition/refinement/flows/do_nothing_refiner.h" +#include "mt-kahypar/partition/refinement/flows/scheduler.h" +#include "mt-kahypar/partition/refinement/flows/flow_refiner.h" #include "mt-kahypar/partition/refinement/gains/gain_definitions.h" +#include "mt-kahypar/partition/refinement/rebalancing/simple_rebalancer.h" +#include "mt-kahypar/partition/refinement/rebalancing/advanced_rebalancer.h" + + +namespace mt_kahypar { +using LabelPropagationDispatcher = kahypar::meta::StaticMultiDispatchFactory< + LabelPropagationRefiner, + IRefiner, + kahypar::meta::Typelist>; + +using DeterministicLabelPropagationDispatcher = kahypar::meta::StaticMultiDispatchFactory< + DeterministicLabelPropagationRefiner, + IRefiner, + kahypar::meta::Typelist>; + +using DefaultFMDispatcher = kahypar::meta::StaticMultiDispatchFactory< + MultiTryKWayFM, + IRefiner, + kahypar::meta::Typelist>; + +using UnconstrainedFMDispatcher = DefaultFMDispatcher; + +using GainCacheFMStrategyDispatcher = kahypar::meta::StaticMultiDispatchFactory< + GainCacheStrategy, + IFMStrategy, + kahypar::meta::Typelist>; + +using UnconstrainedFMStrategyDispatcher = kahypar::meta::StaticMultiDispatchFactory< + UnconstrainedStrategy, + IFMStrategy, + kahypar::meta::Typelist>; + +using FlowSchedulerDispatcher = kahypar::meta::StaticMultiDispatchFactory< + FlowRefinementScheduler, + IRefiner, + kahypar::meta::Typelist>; + +using SimpleRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< + SimpleRebalancer, + IRebalancer, + kahypar::meta::Typelist>; + +using AdvancedRebalancerDispatcher = kahypar::meta::StaticMultiDispatchFactory< + AdvancedRebalancer, + IRebalancer, + kahypar::meta::Typelist>; + +using FlowRefinementDispatcher = kahypar::meta::StaticMultiDispatchFactory< + FlowRefiner, + IFlowRefiner, + kahypar::meta::Typelist>; + #define REGISTER_DISPATCHED_LP_REFINER(id, dispatcher, ...) \ static kahypar::meta::Registrar register_ ## dispatcher( \ @@ -134,7 +196,7 @@ return new refiner(num_Hyperedges, context); \ }) -namespace mt_kahypar { + kahypar::meta::PolicyBase& getCombinedTraitsPolicy(mt_kahypar_partition_type_t partition_type, GainPolicy gain_policy) { switch ( partition_type ) { case MULTILEVEL_HYPERGRAPH_PARTITIONING: SWITCH_HYPERGRAPH_GAIN_TYPES(StaticHypergraphTypeTraits, gain_policy); From 46d263af221903661058faf2a0aeffb08bfdb46a Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 14 Sep 2023 12:26:35 +0200 Subject: [PATCH 13/18] [compile time] separate cpp file for register_initial_partitioning_algorithms This splits the long compile time of pool_initial_partitioner in two --- .../initial_partitioning_commons.h | 12 +++++++++++- .../initial_partitioning_data_container.h | 2 -- .../pool_initial_partitioner.cpp | 3 ++- .../initial_partitioning/pool_initial_partitioner.h | 2 -- mt-kahypar/partition/registries/CMakeLists.txt | 1 + ... => register_initial_partitioning_algorithms.cpp} | 7 ------- .../pool_initial_partitioner_test.cc | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) rename mt-kahypar/partition/registries/{register_initial_partitioning_algorithms.h => register_initial_partitioning_algorithms.cpp} (97%) diff --git a/mt-kahypar/partition/initial_partitioning/initial_partitioning_commons.h b/mt-kahypar/partition/initial_partitioning/initial_partitioning_commons.h index ab781e37c..45e294c5e 100644 --- a/mt-kahypar/partition/initial_partitioning/initial_partitioning_commons.h +++ b/mt-kahypar/partition/initial_partitioning/initial_partitioning_commons.h @@ -31,15 +31,25 @@ #include "kahypar-resources/datastructure/kway_priority_queue.h" #pragma GCC diagnostic pop +#include "kahypar-resources/datastructure/fast_reset_flag_array.h" +#include "kahypar-resources/meta/abstract_factory.h" + #include "tbb/enumerable_thread_specific.h" + #include "mt-kahypar/datastructures/hypergraph_common.h" -#include "kahypar-resources/datastructure/fast_reset_flag_array.h" +#include "mt-kahypar/definitions.h" +#include "mt-kahypar/partition/initial_partitioning/i_initial_partitioner.h" namespace mt_kahypar { +typedef struct ip_data_container_s ip_data_container_t; + using KWayPriorityQueue = kahypar::ds::KWayPriorityQueue, false>; using ThreadLocalKWayPriorityQueue = tbb::enumerable_thread_specific; using ThreadLocalFastResetFlagArray = tbb::enumerable_thread_specific >; +using InitialPartitionerFactory = kahypar::meta::Factory; + } \ No newline at end of file diff --git a/mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h b/mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h index ea76a660c..178f3a33d 100644 --- a/mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h +++ b/mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h @@ -714,8 +714,6 @@ class InitialPartitioningDataContainer { vec< std::pair> > _best_partitions; }; -typedef struct ip_data_container_s ip_data_container_t; - namespace ip { template ip_data_container_t* to_pointer(InitialPartitioningDataContainer& ip_data) { diff --git a/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.cpp b/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.cpp index aad41ed8e..81a04ac59 100644 --- a/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.cpp +++ b/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.cpp @@ -29,7 +29,8 @@ #include "tbb/task_group.h" #include "mt-kahypar/definitions.h" -#include "mt-kahypar/partition/registries/register_initial_partitioning_algorithms.h" +#include "mt-kahypar/partition/initial_partitioning/i_initial_partitioner.h" +#include "mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h" #include "mt-kahypar/utils/cast.h" #include "mt-kahypar/utils/exception.h" diff --git a/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h b/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h index 84d504ee1..8de09914a 100644 --- a/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h +++ b/mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h @@ -30,8 +30,6 @@ #include "include/libmtkahypartypes.h" -#include "mt-kahypar/partition/initial_partitioning/initial_partitioning_data_container.h" - namespace mt_kahypar { diff --git a/mt-kahypar/partition/registries/CMakeLists.txt b/mt-kahypar/partition/registries/CMakeLists.txt index a9b0d8d50..293c477de 100644 --- a/mt-kahypar/partition/registries/CMakeLists.txt +++ b/mt-kahypar/partition/registries/CMakeLists.txt @@ -3,6 +3,7 @@ set(RegistrySources register_refinement_algorithms.cpp register_policies.cpp register_coarsening_algorithms.cpp + register_initial_partitioning_algorithms.cpp ) foreach(modtarget IN LISTS PARTITIONING_SUITE_TARGETS) diff --git a/mt-kahypar/partition/registries/register_initial_partitioning_algorithms.h b/mt-kahypar/partition/registries/register_initial_partitioning_algorithms.cpp similarity index 97% rename from mt-kahypar/partition/registries/register_initial_partitioning_algorithms.h rename to mt-kahypar/partition/registries/register_initial_partitioning_algorithms.cpp index 5f2816458..0a8035c2b 100644 --- a/mt-kahypar/partition/registries/register_initial_partitioning_algorithms.h +++ b/mt-kahypar/partition/registries/register_initial_partitioning_algorithms.cpp @@ -25,9 +25,6 @@ * SOFTWARE. ******************************************************************************/ -#pragma once - -#include "kahypar-resources/meta/abstract_factory.h" #include "kahypar-resources/meta/static_multi_dispatch_factory.h" #include "kahypar-resources/meta/typelist.h" #include "kahypar-resources/meta/registrar.h" @@ -42,10 +39,6 @@ #include "mt-kahypar/partition/initial_partitioning/policies/gain_computation_policy.h" #include "mt-kahypar/partition/initial_partitioning/policies/pq_selection_policy.h" -namespace mt_kahypar { -using InitialPartitionerFactory = kahypar::meta::Factory; -} #define REGISTER_DISPATCHED_INITIAL_PARTITIONER(id, dispatcher, ...) \ static kahypar::meta::Registrar register_ ## dispatcher( \ diff --git a/tests/partition/initial_partitioning/pool_initial_partitioner_test.cc b/tests/partition/initial_partitioning/pool_initial_partitioner_test.cc index 754d1ebf5..f3497535e 100644 --- a/tests/partition/initial_partitioning/pool_initial_partitioner_test.cc +++ b/tests/partition/initial_partitioning/pool_initial_partitioner_test.cc @@ -33,8 +33,8 @@ #include "mt-kahypar/definitions.h" #include "mt-kahypar/utils/utilities.h" #include "mt-kahypar/io/hypergraph_factory.h" -#include "mt-kahypar/partition/registries/register_initial_partitioning_algorithms.h" #include "mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h" +#include "mt-kahypar/partition/metrics.h" using ::testing::Test; From b6376c78fe7a42a459c7c69adb28338e50d00131 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 14 Sep 2023 13:20:35 +0200 Subject: [PATCH 14/18] [compile time] refactor greedy initial partitioner into base and subclass reduces compile time of register_initial_partitioning_algorithms significantly --- .../greedy_initial_partitioner.h | 119 +++++++++++------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/mt-kahypar/partition/initial_partitioning/greedy_initial_partitioner.h b/mt-kahypar/partition/initial_partitioning/greedy_initial_partitioner.h index e870026d2..4ae7c1655 100644 --- a/mt-kahypar/partition/initial_partitioning/greedy_initial_partitioner.h +++ b/mt-kahypar/partition/initial_partitioning/greedy_initial_partitioner.h @@ -31,35 +31,31 @@ #include "mt-kahypar/partition/initial_partitioning/policies/pseudo_peripheral_start_nodes.h" namespace mt_kahypar { -template typename GainPolicyT, - template typename PQSelectionPolicyT> -class GreedyInitialPartitioner : public IInitialPartitioner { +template typename GainPolicyT> +class GreedyInitialPartitionerBase { using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; using GainComputationPolicy = GainPolicyT; - using PQSelectionPolicy = PQSelectionPolicyT; - using DeltaFunction = std::function; - #define NOOP_FUNC [] (const SynchronizedEdgeUpdate&) { } static constexpr bool debug = false; static constexpr bool enable_heavy_assert = false; public: - GreedyInitialPartitioner(const InitialPartitioningAlgorithm algorithm, - ip_data_container_t* ip_data, - const Context& context, - const int seed, const int tag) : + GreedyInitialPartitionerBase(const InitialPartitioningAlgorithm algorithm, + ip_data_container_t* ip_data, + const Context& context, + const PartitionID default_block, + const int seed, const int tag) : _algorithm(algorithm), _ip_data(ip::to_reference(ip_data)), _context(context), - _default_block(PQSelectionPolicy::getDefaultBlock()), + _default_block(default_block), _rng(seed), _tag(tag) { } - private: - void partitionImpl() final { + template + void partitionWithSelectionPolicy() { if ( _ip_data.should_initial_partitioner_run(_algorithm) ) { HighResClockTimepoint start = std::chrono::high_resolution_clock::now(); PartitionedHypergraph& hg = _ip_data.local_partitioned_hypergraph(); @@ -67,37 +63,8 @@ class GreedyInitialPartitioner : public IInitialPartitioner { kahypar::ds::FastResetFlagArray<>& hyperedges_in_queue = _ip_data.local_hyperedge_fast_reset_flag_array(); - // Experiments have shown that some pq selection policies work better - // if we preassign all vertices to a block and than execute the greedy - // initial partitioner. E.g. the round-robin variant leaves the hypernode - // unassigned, but the global and sequential strategy both preassign - // all vertices to block 1 before initial partitioning. - _ip_data.preassignFixedVertices(hg); - if ( _default_block != kInvalidPartition ) { - ASSERT(_default_block < _context.partition.k); - kway_pq.disablePart(_default_block); - for ( const HypernodeID& hn : hg.nodes() ) { - if ( !hg.isFixed(hn) ) { - hg.setNodePart(hn, _default_block); - } - } - } + initializeVertices(); - // Insert start vertices into its corresponding PQs - _ip_data.reset_unassigned_hypernodes(_rng); - vec> start_nodes = - PseudoPeripheralStartNodes::computeStartNodes(_ip_data, _context, _default_block, _rng); - ASSERT(static_cast(_context.partition.k) == start_nodes.size()); - kway_pq.clear(); - for ( PartitionID block = 0; block < _context.partition.k; ++block ) { - if ( block != _default_block ) { - for ( const HypernodeID& hn : start_nodes[block] ) { - insertVertexIntoPQ(hg, kway_pq, hn, block); - } - } - } - - hyperedges_in_queue.reset(); PartitionID to = kInvalidPartition; bool use_perfect_balanced_as_upper_bound = true; bool allow_overfitting = false; @@ -151,13 +118,50 @@ class GreedyInitialPartitioner : public IInitialPartitioner { } } - HighResClockTimepoint end = std::chrono::high_resolution_clock::now(); double time = std::chrono::duration(end - start).count(); _ip_data.commit(_algorithm, _rng, _tag, time); } } + private: + void initializeVertices() { + PartitionedHypergraph& hg = _ip_data.local_partitioned_hypergraph(); + KWayPriorityQueue& kway_pq = _ip_data.local_kway_priority_queue(); + + // Experiments have shown that some pq selection policies work better + // if we preassign all vertices to a block and than execute the greedy + // initial partitioner. E.g. the round-robin variant leaves the hypernode + // unassigned, but the global and sequential strategy both preassign + // all vertices to block 1 before initial partitioning. + _ip_data.preassignFixedVertices(hg); + if ( _default_block != kInvalidPartition ) { + ASSERT(_default_block < _context.partition.k); + kway_pq.disablePart(_default_block); + for ( const HypernodeID& hn : hg.nodes() ) { + if ( !hg.isFixed(hn) ) { + hg.setNodePart(hn, _default_block); + } + } + } + + // Insert start vertices into its corresponding PQs + _ip_data.reset_unassigned_hypernodes(_rng); + vec> start_nodes = + PseudoPeripheralStartNodes::computeStartNodes(_ip_data, _context, _default_block, _rng); + ASSERT(static_cast(_context.partition.k) == start_nodes.size()); + kway_pq.clear(); + for ( PartitionID block = 0; block < _context.partition.k; ++block ) { + if ( block != _default_block ) { + for ( const HypernodeID& hn : start_nodes[block] ) { + insertVertexIntoPQ(hg, kway_pq, hn, block); + } + } + } + + _ip_data.local_hyperedge_fast_reset_flag_array().reset(); + } + bool fitsIntoBlock(PartitionedHypergraph& hypergraph, const HypernodeID hn, const PartitionID block, @@ -257,4 +261,29 @@ class GreedyInitialPartitioner : public IInitialPartitioner { const int _tag; }; + +// the split into base and subclass serves to reduce the compile time, since the base class +// is only instantiated once for all PQ selection policies +template typename GainPolicyT, + template typename PQSelectionPolicyT> +class GreedyInitialPartitioner : public IInitialPartitioner, GreedyInitialPartitionerBase { + + using Base = GreedyInitialPartitionerBase; + using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + using PQSelectionPolicy = PQSelectionPolicyT; + + public: + GreedyInitialPartitioner(const InitialPartitioningAlgorithm algorithm, + ip_data_container_t* ip_data, + const Context& context, + const int seed, const int tag) : + Base(algorithm, ip_data, context, PQSelectionPolicy::getDefaultBlock(), seed, tag) { } + + private: + void partitionImpl() final { + Base::template partitionWithSelectionPolicy(); + } +}; + } // namespace mt_kahypar From c07262df9adb430342c6f5b6f00b10bf252d2ed3 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Wed, 13 Sep 2023 11:37:47 +0200 Subject: [PATCH 15/18] [compile time] adjust compilation order to start expensive jobs first ~10% improvement for clean builds --- mt-kahypar/CMakeLists.txt | 2 +- mt-kahypar/partition/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mt-kahypar/CMakeLists.txt b/mt-kahypar/CMakeLists.txt index aceccf625..76ae5502f 100644 --- a/mt-kahypar/CMakeLists.txt +++ b/mt-kahypar/CMakeLists.txt @@ -1,6 +1,6 @@ +add_subdirectory(partition) add_subdirectory(datastructures) add_subdirectory(io) -add_subdirectory(partition) add_subdirectory(utils) foreach(modtarget IN LISTS PARTITIONING_SUITE_TARGETS) diff --git a/mt-kahypar/partition/CMakeLists.txt b/mt-kahypar/partition/CMakeLists.txt index d2fe7c0c1..1a05c4130 100644 --- a/mt-kahypar/partition/CMakeLists.txt +++ b/mt-kahypar/partition/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(mapping) add_subdirectory(registries) set(PartitionSources + deep_multilevel.cpp partitioner.cpp partitioner_facade.cpp multilevel.cpp @@ -14,7 +15,6 @@ set(PartitionSources conversion.cpp metrics.cpp recursive_bipartitioning.cpp - deep_multilevel.cpp ) foreach(modtarget IN LISTS PARTITIONING_SUITE_TARGETS) From 2774e65167b95e1742adc1478a85417445ff24d5 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 14 Sep 2023 15:18:44 +0200 Subject: [PATCH 16/18] refactor gain_cache_ptr --- .../refinement/gains/gain_cache_ptr.h | 214 +++++++----------- 1 file changed, 83 insertions(+), 131 deletions(-) diff --git a/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h b/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h index 2ebf5333d..ce0c5ac9c 100644 --- a/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h +++ b/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h @@ -29,8 +29,10 @@ #include "kahypar-resources/meta/typelist.h" #include "mt-kahypar/definitions.h" +#include "mt-kahypar/macros.h" #include "mt-kahypar/partition/context_enum_classes.h" #include "mt-kahypar/datastructures/hypergraph_common.h" +#include "mt-kahypar/partition/refinement/gains/gain_definitions.h" #include "mt-kahypar/partition/refinement/gains/km1/km1_gain_cache.h" #include "mt-kahypar/partition/refinement/gains/cut/cut_gain_cache.h" #include "mt-kahypar/partition/refinement/gains/soed/soed_gain_cache.h" @@ -57,96 +59,110 @@ typedef struct { class GainCachePtr { public: - static gain_cache_t constructGainCache(const Context& context) { - switch(context.partition.gain_policy) { - case GainPolicy::cut: return constructGainCache(context); - case GainPolicy::km1: return constructGainCache(context); + template + static auto applyWithConcreteGainCache(F function, gain_cache_t gain_cache) { + switch(gain_cache.type) { + case GainPolicy::cut: + return function(cast(gain_cache)); + case GainPolicy::km1: + return function(cast(gain_cache)); + case GainPolicy::soed: #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: return constructGainCache(context); + return function(cast(gain_cache)); #endif + case GainPolicy::steiner_tree: #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: return constructGainCache(context); + return function(cast(gain_cache)); #endif - ENABLE_GRAPHS(case GainPolicy::cut_for_graphs: return constructGainCache(context);) + case GainPolicy::cut_for_graphs: + #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES + return function(cast(gain_cache)); + #endif + case GainPolicy::steiner_tree_for_graphs: #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - ENABLE_GRAPHS(case GainPolicy::steiner_tree_for_graphs: return constructGainCache(context);) + #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES + return function(cast(gain_cache)); #endif - case GainPolicy::none: - throw InvalidParameterException("No gain policy set"); - default: break; + #endif + case GainPolicy::none: break; } - return gain_cache_t { nullptr, GainPolicy::none }; + ERROR("No gain policy set"); } - static void deleteGainCache(gain_cache_t gain_cache) { - if ( gain_cache.gain_cache ) { + template + static auto applyWithConcreteGainCacheForHG(F function, gain_cache_t gain_cache) { + if constexpr (Hypergraph::is_graph) { + switch(gain_cache.type) { + #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES + case GainPolicy::cut_for_graphs: + return function(cast(gain_cache)); + #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC + case GainPolicy::steiner_tree_for_graphs: + return function(cast(gain_cache)); + #endif + #endif + default: break; + } + } else { switch(gain_cache.type) { case GainPolicy::cut: - delete reinterpret_cast(gain_cache.gain_cache); break; + return function(cast(gain_cache)); case GainPolicy::km1: - delete reinterpret_cast(gain_cache.gain_cache); break; + return function(cast(gain_cache)); #ifdef KAHYPAR_ENABLE_SOED_METRIC case GainPolicy::soed: - delete reinterpret_cast(gain_cache.gain_cache); break; + return function(cast(gain_cache)); #endif #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC case GainPolicy::steiner_tree: - delete reinterpret_cast(gain_cache.gain_cache); break; + return function(cast(gain_cache)); #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: - delete reinterpret_cast(gain_cache.gain_cache); break; - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: - delete reinterpret_cast(gain_cache.gain_cache); break; - #endif - #endif - case GainPolicy::none: break; default: break; } } + ERROR("No gain policy set"); } - template - static void initializeGainCache(const PartitionedHypergraph& partitioned_hg, - gain_cache_t gain_cache) { - switch(gain_cache.type) { - case GainPolicy::cut: cast(gain_cache).initializeGainCache(partitioned_hg); break; - case GainPolicy::km1: cast(gain_cache).initializeGainCache(partitioned_hg); break; + static gain_cache_t constructGainCache(const Context& context) { + switch(context.partition.gain_policy) { + case GainPolicy::cut: return constructGainCache(context); + case GainPolicy::km1: return constructGainCache(context); #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: cast(gain_cache).initializeGainCache(partitioned_hg); break; + case GainPolicy::soed: return constructGainCache(context); #endif #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: cast(gain_cache).initializeGainCache(partitioned_hg); break; + case GainPolicy::steiner_tree: return constructGainCache(context); #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: cast(gain_cache).initializeGainCache(partitioned_hg); break; + ENABLE_GRAPHS(case GainPolicy::cut_for_graphs: return constructGainCache(context);) #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: cast(gain_cache).initializeGainCache(partitioned_hg); break; - #endif + ENABLE_GRAPHS(case GainPolicy::steiner_tree_for_graphs: return constructGainCache(context);) #endif + case GainPolicy::none: + throw InvalidParameterException("No gain policy set"); default: break; } + return gain_cache_t { nullptr, GainPolicy::none }; + } + + static void deleteGainCache(gain_cache_t gain_cache) { + if (gain_cache.type != GainPolicy::none) { + applyWithConcreteGainCache([&](auto& gc) { delete &gc; }, gain_cache); + } + } + + template + static void initializeGainCache(const PartitionedHypergraph& partitioned_hg, + gain_cache_t gain_cache) { + if (gain_cache.type != GainPolicy::none) { + applyWithConcreteGainCacheForHG([&](auto& gc) { + gc.initializeGainCache(partitioned_hg); + }, gain_cache); + } } static void resetGainCache(gain_cache_t gain_cache) { - switch(gain_cache.type) { - case GainPolicy::cut: cast(gain_cache).reset(); break; - case GainPolicy::km1: cast(gain_cache).reset(); break; - #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: cast(gain_cache).reset(); break; - #endif - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: cast(gain_cache).reset(); break; - #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: cast(gain_cache).reset(); break; - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: cast(gain_cache).reset(); break; - #endif - #endif - case GainPolicy::none: break; - default: break; + if (gain_cache.type != GainPolicy::none) { + applyWithConcreteGainCache([&](auto& gc) { gc.reset(); }, gain_cache); } } @@ -154,21 +170,10 @@ class GainCachePtr { static void uncontract(PartitionedHypergraph& partitioned_hg, const Batch& batch, gain_cache_t gain_cache) { - switch(gain_cache.type) { - case GainPolicy::cut: partitioned_hg.uncontract(batch, cast(gain_cache)); break; - case GainPolicy::km1: partitioned_hg.uncontract(batch, cast(gain_cache)); break; - #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: partitioned_hg.uncontract(batch, cast(gain_cache)); break; - #endif - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: partitioned_hg.uncontract(batch, cast(gain_cache)); break; - #endif - ENABLE_GRAPHS(case GainPolicy::cut_for_graphs: partitioned_hg.uncontract(batch, cast(gain_cache)); break;) - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - ENABLE_GRAPHS(case GainPolicy::steiner_tree_for_graphs: partitioned_hg.uncontract(batch, cast(gain_cache)); break;) - #endif - case GainPolicy::none: break; - default: break; + if (gain_cache.type != GainPolicy::none) { + applyWithConcreteGainCacheForHG([&](auto& gc) { + partitioned_hg.uncontract(batch, gc); + }, gain_cache); } } @@ -176,72 +181,19 @@ class GainCachePtr { static void restoreSinglePinAndParallelNets(PartitionedHypergraph& partitioned_hg, const vec& hes_to_restore, gain_cache_t gain_cache) { - switch ( gain_cache.type ) { - case GainPolicy::cut: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - case GainPolicy::km1: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - #endif - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: - partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, - cast(gain_cache)); break; - #endif - #endif - case GainPolicy::none: break; - default: break; + if (gain_cache.type != GainPolicy::none) { + applyWithConcreteGainCacheForHG([&](auto& gc) { + partitioned_hg.restoreSinglePinAndParallelNets(hes_to_restore, gc); + }, gain_cache); } } template static bool checkTrackedPartitionInformation(PartitionedHypergraph& partitioned_hg, gain_cache_t gain_cache) { - switch ( gain_cache.type ) { - case GainPolicy::cut: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - case GainPolicy::km1: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - #endif - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: - return partitioned_hg.checkTrackedPartitionInformation( - cast(gain_cache)); - #endif - #endif - case GainPolicy::none: return false; - default: break; - } - return false; + return applyWithConcreteGainCacheForHG([&](auto& gc) { + return partitioned_hg.checkTrackedPartitionInformation(gc); + }, gain_cache); } template From 684e730402bac136ab395f5ac7d7854da0fd62fb Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Thu, 14 Sep 2023 15:19:17 +0200 Subject: [PATCH 17/18] [compile time] reduce templated code in deep multilevel --- mt-kahypar/partition/deep_multilevel.cpp | 161 ++++++++++------------- 1 file changed, 66 insertions(+), 95 deletions(-) diff --git a/mt-kahypar/partition/deep_multilevel.cpp b/mt-kahypar/partition/deep_multilevel.cpp index d5c684277..d200a496b 100644 --- a/mt-kahypar/partition/deep_multilevel.cpp +++ b/mt-kahypar/partition/deep_multilevel.cpp @@ -31,18 +31,17 @@ #include #include -#include "tbb/parallel_invoke.h" +#include "tbb/parallel_for.h" #include "mt-kahypar/definitions.h" #include "mt-kahypar/macros.h" +#include "mt-kahypar/partition/metrics.h" #include "mt-kahypar/partition/multilevel.h" +#include "mt-kahypar/partition/coarsening/coarsening_commons.h" #include "mt-kahypar/partition/coarsening/multilevel_uncoarsener.h" #include "mt-kahypar/partition/coarsening/nlevel_uncoarsener.h" -#include "mt-kahypar/partition/initial_partitioning/pool_initial_partitioner.h" -#include "mt-kahypar/partition/preprocessing/sparsification/degree_zero_hn_remover.h" #include "mt-kahypar/partition/refinement/gains/gain_cache_ptr.h" #include "mt-kahypar/partition/refinement/gains/bipartitioning_policy.h" -#include "mt-kahypar/utils/randomize.h" #include "mt-kahypar/utils/utilities.h" #include "mt-kahypar/utils/timer.h" #include "mt-kahypar/utils/progress_bar.h" @@ -279,19 +278,18 @@ void enableTimerAndStats(const Context& context, const bool was_enabled_before) } } -template -Context setupBipartitioningContext(const Hypergraph& hypergraph, - const Context& context, +Context setupBipartitioningContext(const Context& context, const OriginalHypergraphInfo& info, const PartitionID start_k, - const PartitionID end_k) { + const PartitionID end_k, + const HypernodeWeight total_weight, + const bool is_graph) { ASSERT(end_k - start_k >= 2); Context b_context(context); b_context.partition.k = 2; b_context.partition.objective = Objective::cut; - b_context.partition.gain_policy = Hypergraph::is_graph ? - GainPolicy::cut_for_graphs : GainPolicy::cut; + b_context.partition.gain_policy = is_graph ? GainPolicy::cut_for_graphs : GainPolicy::cut; b_context.partition.verbose_output = false; b_context.initial_partitioning.mode = Mode::direct; b_context.type = ContextType::initial_partitioning; @@ -306,7 +304,6 @@ Context setupBipartitioningContext(const Hypergraph& hypergraph, b_context.refinement = b_context.initial_partitioning.refinement; // Setup Part Weights - const HypernodeWeight total_weight = hypergraph.totalWeight(); const PartitionID k = end_k - start_k; const PartitionID k0 = k / 2 + (k % 2 != 0 ? 1 : 0); const PartitionID k1 = k / 2; @@ -472,7 +469,7 @@ DeepPartitioningResult bipartition_block(typename TypeTraits::Hyperg if ( bipartition.hypergraph.initialNumNodes() > 0 ) { // Bipartition block Context b_context = setupBipartitioningContext( - bipartition.hypergraph, context, info, start_k, end_k); + context, info, start_k, end_k, bipartition.hypergraph.totalWeight(), PartitionedHypergraph::is_graph); bipartition.partitioned_hg = Multilevel::partition( bipartition.hypergraph, b_context); } else { @@ -483,9 +480,61 @@ DeepPartitioningResult bipartition_block(typename TypeTraits::Hyperg } template +void apply_bipartitions_to_hypergraph(typename TypeTraits::PartitionedHypergraph& partitioned_hg, + GainCache& gain_cache, + const vec& mapping, + const vec>& bipartitions, + const vec& block_ranges) { + partitioned_hg.doParallelForAllNodes([&](const HypernodeID& hn) { + const PartitionID from = partitioned_hg.partID(hn); + ASSERT(static_cast(from) < bipartitions.size()); + PartitionID to = kInvalidPartition; + const DeepPartitioningResult& bipartition = bipartitions[from]; + if ( bipartition.valid ) { + ASSERT(static_cast(hn) < mapping.size()); + const HypernodeID mapped_hn = mapping[hn]; + to = bipartition.partitioned_hg.partID(mapped_hn) == 0 ? + block_ranges[from] : block_ranges[from] + 1; + } else { + to = block_ranges[from]; + } + + ASSERT(to > kInvalidPartition && to < block_ranges.back()); + if ( from != to ) { + if ( gain_cache.isInitialized() ) { + partitioned_hg.changeNodePart(gain_cache, hn, from, to); + } else { + partitioned_hg.changeNodePart(hn, from, to); + } + } + }); + + if ( GainCache::invalidates_entries && gain_cache.isInitialized() ) { + partitioned_hg.doParallelForAllNodes([&](const HypernodeID& hn) { + gain_cache.recomputeInvalidTerms(partitioned_hg, hn); + }); + } + + HEAVY_REFINEMENT_ASSERT(partitioned_hg.checkTrackedPartitionInformation(gain_cache)); +} + +template +void apply_bipartitions_to_hypergraph(typename TypeTraits::PartitionedHypergraph& partitioned_hg, + gain_cache_t gain_cache, + const vec& mapping, + const vec>& bipartitions, + const vec& block_ranges) { + using PartitionedHypergraph = typename TypeTraits::PartitionedHypergraph; + + GainCachePtr::applyWithConcreteGainCacheForHG([&](auto& gain_cache) { + apply_bipartitions_to_hypergraph(partitioned_hg,gain_cache, mapping, bipartitions, block_ranges); + }, gain_cache); +} + +template void bipartition_each_block(typename TypeTraits::PartitionedHypergraph& partitioned_hg, const Context& context, - GainCache& gain_cache, + gain_cache_t gain_cache, const OriginalHypergraphInfo& info, const RBTree& rb_tree, vec& already_cut, @@ -551,30 +600,8 @@ void bipartition_each_block(typename TypeTraits::PartitionedHypergraph& partitio timer.stop_timer("bipartition_blocks"); timer.start_timer("apply_bipartitions", "Apply Bipartition"); - // Apply all bipartitions to current hypergraph - partitioned_hg.doParallelForAllNodes([&](const HypernodeID& hn) { - const PartitionID from = partitioned_hg.partID(hn); - ASSERT(static_cast(from) < bipartitions.size()); - PartitionID to = kInvalidPartition; - const DeepPartitioningResult& bipartition = bipartitions[from]; - if ( bipartition.valid ) { - ASSERT(static_cast(hn) < mapping.size()); - const HypernodeID mapped_hn = mapping[hn]; - to = bipartition.partitioned_hg.partID(mapped_hn) == 0 ? - block_ranges[from] : block_ranges[from] + 1; - } else { - to = block_ranges[from]; - } - - ASSERT(to > kInvalidPartition && to < block_ranges.back()); - if ( from != to ) { - if ( gain_cache.isInitialized() ) { - partitioned_hg.changeNodePart(gain_cache, hn, from, to); - } else { - partitioned_hg.changeNodePart(hn, from, to); - } - } - }); + apply_bipartitions_to_hypergraph(partitioned_hg, gain_cache, mapping, bipartitions, block_ranges); + timer.stop_timer("apply_bipartitions"); ASSERT([&] { HyperedgeWeight expected_objective = current_objective; @@ -592,69 +619,12 @@ void bipartition_each_block(typename TypeTraits::PartitionedHypergraph& partitio return true; }(), "Cut of extracted blocks does not sum up to current objective"); - if ( GainCache::invalidates_entries && gain_cache.isInitialized() ) { - partitioned_hg.doParallelForAllNodes([&](const HypernodeID& hn) { - gain_cache.recomputeInvalidTerms(partitioned_hg, hn); - }); - } - timer.stop_timer("apply_bipartitions"); - timer.start_timer("free_hypergraphs", "Free Hypergraphs"); tbb::parallel_for(UL(0), bipartitions.size(), [&](const size_t i) { DeepPartitioningResult tmp_res; tmp_res = std::move(bipartitions[i]); }); timer.stop_timer("free_hypergraphs"); - - HEAVY_REFINEMENT_ASSERT(partitioned_hg.checkTrackedPartitionInformation(gain_cache)); -} - -template -void bipartition_each_block(typename TypeTraits::PartitionedHypergraph& partitioned_hg, - const Context& context, - gain_cache_t gain_cache, - const OriginalHypergraphInfo& info, - const RBTree& rb_tree, - vec& already_cut, - const PartitionID current_k, - const HyperedgeWeight current_objective, - const bool progress_bar_enabled) { - switch(gain_cache.type) { - case GainPolicy::cut: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - case GainPolicy::km1: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - #ifdef KAHYPAR_ENABLE_SOED_METRIC - case GainPolicy::soed: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - #endif - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - #endif - #ifdef KAHYPAR_ENABLE_GRAPH_PARTITIONING_FEATURES - case GainPolicy::cut_for_graphs: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC - case GainPolicy::steiner_tree_for_graphs: - bipartition_each_block(partitioned_hg, context, - GainCachePtr::cast(gain_cache), info, rb_tree, - already_cut, current_k, current_objective, progress_bar_enabled); break; - #endif - #endif - case GainPolicy::none: break; - default: break; - } } template @@ -768,7 +738,8 @@ PartitionID deep_multilevel_partitioning(typename TypeTraits::PartitionedHypergr // and continue with uncoarsening. const auto target_blocks = rb_tree.targetBlocksInFinalPartition(1, 0); Context b_context = setupBipartitioningContext( - hypergraph, context, info, target_blocks.first, target_blocks.second); + context, info, target_blocks.first, target_blocks.second, + hypergraph.totalWeight(), Hypergraph::is_graph); Multilevel::partition(coarsest_phg, b_context); current_k = 2; From 8e8d601cdb5bb71c83615748e5f603f1a2769d42 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Fri, 29 Sep 2023 13:44:12 +0200 Subject: [PATCH 18/18] fix --- mt-kahypar/partition/refinement/gains/gain_cache_ptr.h | 4 ++-- mt-kahypar/partition/refinement/gains/gain_definitions.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h b/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h index ce0c5ac9c..49b046f0f 100644 --- a/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h +++ b/mt-kahypar/partition/refinement/gains/gain_cache_ptr.h @@ -86,7 +86,7 @@ class GainCachePtr { #endif case GainPolicy::none: break; } - ERROR("No gain policy set"); + ERR("No gain policy set"); } template @@ -120,7 +120,7 @@ class GainCachePtr { default: break; } } - ERROR("No gain policy set"); + ERR("No gain policy set"); } static gain_cache_t constructGainCache(const Context& context) { diff --git a/mt-kahypar/partition/refinement/gains/gain_definitions.h b/mt-kahypar/partition/refinement/gains/gain_definitions.h index 69bdaed33..52135f592 100644 --- a/mt-kahypar/partition/refinement/gains/gain_definitions.h +++ b/mt-kahypar/partition/refinement/gains/gain_definitions.h @@ -206,7 +206,7 @@ using ValidTraitCombinations = kahypar::meta::Typelist<_LIST_HYPERGRAPH_COMBINAT case GainPolicy::steiner_tree: \ ENABLE_STEINER_TREE(_RETURN_COMBINED_POLICY(TYPE_TRAITS, SteinerTreeGainTypes)) \ default: { \ - ERROR("Invalid gain policy type"); \ + ERR("Invalid gain policy type"); \ } \ } \ } @@ -218,7 +218,7 @@ using ValidTraitCombinations = kahypar::meta::Typelist<_LIST_HYPERGRAPH_COMBINAT case GainPolicy::steiner_tree_for_graphs: \ ENABLE_STEINER_TREE(ENABLE_GRAPHS(_RETURN_COMBINED_POLICY(TYPE_TRAITS, SteinerTreeForGraphsTypes))) \ default: { \ - ERROR("Invalid gain policy type"); \ + ERR("Invalid gain policy type"); \ } \ } \ }