From ac743415e9e7d713da55bc661909a8f8e57f2d8b Mon Sep 17 00:00:00 2001 From: Daniel Seemaier Date: Tue, 7 May 2024 12:09:39 +0200 Subject: [PATCH] feat: add largek gain cache (inaccurate gain cache that does not always iterate over all blocks) --- kaminpar-shm/context_io.cc | 7 +++++-- kaminpar-shm/kaminpar.h | 2 ++ kaminpar-shm/presets.cc | 17 +++++++++++++++++ kaminpar-shm/refinement/fm/fm_refiner.cc | 3 +++ .../refinement/gains/dense_gain_cache.h | 10 +++++++--- 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/kaminpar-shm/context_io.cc b/kaminpar-shm/context_io.cc index 76fcc232..d4c843c1 100644 --- a/kaminpar-shm/context_io.cc +++ b/kaminpar-shm/context_io.cc @@ -240,6 +240,7 @@ std::unordered_map get_gain_cache_strategies() { return { {"sparse", GainCacheStrategy::SPARSE}, {"dense", GainCacheStrategy::DENSE}, + {"largek", GainCacheStrategy::LARGE_K}, {"on-the-fly", GainCacheStrategy::ON_THE_FLY}, {"hybrid", GainCacheStrategy::HYBRID}, {"tracing", GainCacheStrategy::TRACING}, @@ -252,6 +253,8 @@ std::ostream &operator<<(std::ostream &out, const GainCacheStrategy strategy) { return out << "sparse"; case GainCacheStrategy::DENSE: return out << "dense"; + case GainCacheStrategy::LARGE_K: + return out << "largek"; case GainCacheStrategy::ON_THE_FLY: return out << "on-the-fly"; case GainCacheStrategy::HYBRID: @@ -567,8 +570,8 @@ void print(const Context &ctx, std::ostream &out) { out << "Execution mode: " << ctx.parallel.num_threads << "\n"; out << "Seed: " << Random::get_seed() << "\n"; out << "Graph: " << ctx.debug.graph_name - << " [node ordering: " << ctx.node_ordering << "]" - << " [edge ordering: " << ctx.edge_ordering << "]\n"; + << " [node ordering: " << ctx.node_ordering << "]" << " [edge ordering: " << ctx.edge_ordering + << "]\n"; print(ctx.partition, out); cio::print_delimiter("Graph Compression", '-'); print(ctx.compression, out); diff --git a/kaminpar-shm/kaminpar.h b/kaminpar-shm/kaminpar.h index 163e2288..3284e9e7 100644 --- a/kaminpar-shm/kaminpar.h +++ b/kaminpar-shm/kaminpar.h @@ -202,6 +202,7 @@ enum class FMStoppingRule { enum class GainCacheStrategy { SPARSE, DENSE, + LARGE_K, ON_THE_FLY, HYBRID, TRACING, @@ -434,6 +435,7 @@ Context create_default_context(); Context create_memory_context(); Context create_fast_context(); Context create_largek_context(); +Context create_largek_fm_context(); Context create_strong_context(); Context create_jet_context(); Context create_noref_context(); diff --git a/kaminpar-shm/presets.cc b/kaminpar-shm/presets.cc index 2a030f2f..e60742b0 100644 --- a/kaminpar-shm/presets.cc +++ b/kaminpar-shm/presets.cc @@ -23,6 +23,8 @@ Context create_context_by_preset_name(const std::string &name) { return create_fast_context(); } else if (name == "largek") { return create_largek_context(); + } else if (name == "largek-fm") { + return create_largek_fm_context(); } else if (name == "strong" || name == "fm") { return create_strong_context(); } else if (name == "jet") { @@ -233,6 +235,21 @@ Context create_largek_context() { return ctx; } +Context create_largek_fm_context() { + Context ctx = create_largek_context(); + + ctx.refinement.algorithms = { + RefinementAlgorithm::GREEDY_BALANCER, + RefinementAlgorithm::LEGACY_LABEL_PROPAGATION, + RefinementAlgorithm::KWAY_FM, + RefinementAlgorithm::GREEDY_BALANCER, + }; + + ctx.refinement.kway_fm.gain_cache_strategy = GainCacheStrategy::LARGE_K; + + return ctx; +} + Context create_strong_context() { Context ctx = create_default_context(); diff --git a/kaminpar-shm/refinement/fm/fm_refiner.cc b/kaminpar-shm/refinement/fm/fm_refiner.cc index 118a384f..5f09f7e1 100644 --- a/kaminpar-shm/refinement/fm/fm_refiner.cc +++ b/kaminpar-shm/refinement/fm/fm_refiner.cc @@ -38,6 +38,9 @@ std::unique_ptr create_fm_refiner(const Context &ctx) { case GainCacheStrategy::DENSE: return std::make_unique>>(ctx); + case GainCacheStrategy::LARGE_K: + return std::make_unique>>(ctx); + #ifdef KAMINPAR_EXPERIMENTAL case GainCacheStrategy::SPARSE: return std::make_unique>>(ctx); diff --git a/kaminpar-shm/refinement/gains/dense_gain_cache.h b/kaminpar-shm/refinement/gains/dense_gain_cache.h index 379a223b..b8f4667e 100644 --- a/kaminpar-shm/refinement/gains/dense_gain_cache.h +++ b/kaminpar-shm/refinement/gains/dense_gain_cache.h @@ -565,11 +565,15 @@ template class DenseDelta using DeltaPartitionedGraph = _DeltaPartitionedGraph; using GainCache = _GainCache; - // Delta gain caches can only be used with GainCaches that iterate over all blocks, since there - // might be new connections to non-adjacent blocks in the delta graph. - static_assert(GainCache::kIteratesNonadjacentBlocks); + // Delta gain caches should only be used with GainCaches that iterate over all blocks, since there + // might be new connections to non-adjacent blocks in the delta graph. These connections might be + // missed if the gain cache does not iterate over all blocks. constexpr static bool kIteratesExactGains = GainCache::kIteratesExactGains; + // We do not strictly enforce this to offer an easy large k FM variation. + // @todo can we implement a correct delta gain cache that dos not iterate over all blocks? + // static_assert(GainCache::kIteratesNonadjacentBlocks); + DenseDeltaGainCache(const GainCache &gain_cache, const DeltaPartitionedGraph &d_graph) : _k(d_graph.k()), _gain_cache(gain_cache) {}