From 87f1e06c4187cce7afbbee2e2db1fe12389e5076 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Tue, 12 Jul 2022 18:54:17 +0100 Subject: [PATCH] Small algorithmic improvement of PartContraction::siblingPairFromRelatives Use std::partial_sort for the non-exhaustive case. This is O(n) instead of O(n*log(n)) in the size of the candidate list being sorted. (It actually is O(n*log(k)), but k is constant 6 in the non-exhaustive case). --- src/V3Partition.cpp | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 53f101ae3..6b6aea6d7 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -1541,25 +1541,32 @@ private: if (shortestPrereqs.size() > PART_SIBLING_EDGE_LIMIT) break; } - if (shortestPrereqs.empty()) return; + if (shortestPrereqs.size() <= 1) return; - std::sort(shortestPrereqs.begin(), shortestPrereqs.end(), - [way](const LogicMTask* ap, const LogicMTask* bp) { - const uint32_t aCp = ap->critPathCost(way) + ap->stepCost(); - const uint32_t bCp = bp->critPathCost(way) + bp->stepCost(); - if (aCp != bCp) return aCp < bCp; - return ap->id() < bp->id(); - }); + const auto cmp = [way](const LogicMTask* ap, const LogicMTask* bp) { + const uint32_t aCp = ap->critPathCost(way) + ap->stepCost(); + const uint32_t bCp = bp->critPathCost(way) + bp->stepCost(); + if (aCp != bCp) return aCp < bCp; + return ap->id() < bp->id(); + }; - // Don't make all NxN/2 possible pairs of prereqs, that's a lot - // to cart around. Just make a few pairs. - auto it = shortestPrereqs.cbegin(); - for (unsigned i = 0; exhaustive || (i < 3); ++i) { - if (it == shortestPrereqs.cend()) break; - LogicMTask* const ap = *(it++); - if (it == shortestPrereqs.cend()) break; - LogicMTask* const bp = *(it++); - makeSiblingMC(ap, bp); + // Don't make all possible pairs of prereqs when not requested (non-exhaustive). + // Just make a few pairs. + constexpr size_t MAX_NONEXHAUSTIVE_PAIRS = 3; + + size_t end; // End index of pairs to add to candidates (exclusive) + + if (exhaustive || (shortestPrereqs.size() <= 2 * MAX_NONEXHAUSTIVE_PAIRS)) { + end = shortestPrereqs.size() & ~static_cast(1); // Round down to even + std::sort(shortestPrereqs.begin(), shortestPrereqs.end(), cmp); + } else { + end = 2 * MAX_NONEXHAUSTIVE_PAIRS; + std::partial_sort(shortestPrereqs.begin(), shortestPrereqs.begin() + end, + shortestPrereqs.end(), cmp); + } + + for (size_t i = 0; i < end; i += 2) { + makeSiblingMC(shortestPrereqs[i], shortestPrereqs[i + 1]); } }