From b684f954bbfcd9a18c05110b1124276554ba072e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Oct 2025 17:59:09 -0400 Subject: [PATCH] clusterlin: unidirectional MakeTopological initially (optimization) It suffices to initially only attempt one direction of merges in MakeTopological(), and only try both directions on chunks that are the result of other merges. --- src/cluster_linearize.h | 16 ++++++++++++++++ src/test/util/cluster_linearize.h | 14 +++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h index 164ee0df871..7e20f802339 100644 --- a/src/cluster_linearize.h +++ b/src/cluster_linearize.h @@ -1129,6 +1129,16 @@ public: void MakeTopological() noexcept { Assume(m_suboptimal_chunks.empty()); + /** What direction to initially merge chunks in; one of the two directions is enough. This + * is sufficient because if a non-topological inactive dependency exists between two + * chunks, at least one of the two chunks will eventually be processed in a direction that + * discovers it - either the lower chunk tries upward, or the upper chunk tries downward. + * Chunks that are the result of the merging are always tried in both directions. */ + unsigned init_dir = m_rng.randbool(); + /** Which chunks are the result of merging, and thus need merge attempts in both + * directions. */ + SetType merged_chunks; + // Mark chunks as suboptimal. m_suboptimal_idxs = m_chunk_idxs; for (auto chunk_idx : m_chunk_idxs) { m_suboptimal_chunks.emplace_back(chunk_idx); @@ -1147,9 +1157,12 @@ public: // If what was popped is not currently a chunk, continue. This may // happen when it was merged with something else since being added. if (!m_chunk_idxs[chunk_idx]) continue; + /** What direction(s) to attempt merging in. 1=up, 2=down, 3=both. */ + unsigned direction = merged_chunks[chunk_idx] ? 3 : init_dir + 1; int flip = m_rng.randbool(); for (int i = 0; i < 2; ++i) { if (i ^ flip) { + if (!(direction & 1)) continue; // Attempt to merge the chunk upwards. auto result_up = MergeStep(chunk_idx); if (result_up != INVALID_SET_IDX) { @@ -1157,9 +1170,11 @@ public: m_suboptimal_idxs.Set(result_up); m_suboptimal_chunks.push_back(result_up); } + merged_chunks.Set(result_up); break; } } else { + if (!(direction & 2)) continue; // Attempt to merge the chunk downwards. auto result_down = MergeStep(chunk_idx); if (result_down != INVALID_SET_IDX) { @@ -1167,6 +1182,7 @@ public: m_suboptimal_idxs.Set(result_down); m_suboptimal_chunks.push_back(result_down); } + merged_chunks.Set(result_down); break; } } diff --git a/src/test/util/cluster_linearize.h b/src/test/util/cluster_linearize.h index d56860686e3..3814c3fc453 100644 --- a/src/test/util/cluster_linearize.h +++ b/src/test/util/cluster_linearize.h @@ -403,13 +403,13 @@ inline uint64_t MaxOptimalLinearizationIters(DepGraphIndex cluster_count) static constexpr uint64_t ITERS[65] = { 0, 0, 4, 10, 34, 76, 156, 229, 380, - 432, 517, 678, 896, 1037, 1366, 1464, 1792, - 2060, 2542, 3068, 3116, 4029, 3467, 5324, 5512, - 6481, 7161, 7441, 8183, 8843, 9353, 11104, 11269, - 11791, 11871, 13367, 14259, 14229, 12397, 13581, 18152, - 18737, 16581, 23217, 24044, 29597, 29030, 34069, 34594, - 33630, 26227, 34471, 38815, 40814, 31182, 40305, 34019, - 36582, 55659, 39994, 41277, 42365, 52822, 59733, 67035 + 441, 517, 678, 933, 1037, 1366, 1464, 1711, + 2111, 2542, 3068, 3116, 4029, 3467, 5324, 5402, + 6481, 7161, 7441, 8183, 8843, 9353, 11104, 11455, + 11791, 12570, 13480, 14259, 14525, 12426, 14477, 20201, + 18737, 16581, 23622, 28486, 30652, 33021, 32942, 32745, + 34046, 26227, 34662, 38019, 40814, 31113, 41448, 33968, + 35024, 59207, 42872, 41277, 42365, 51833, 63410, 67035 }; assert(cluster_count < std::size(ITERS)); // Multiply the table number by two, to account for the fact that they are not absolutes.