From a4b11f286e292934123e95307c75a4da489ae4c9 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 14 May 2026 12:39:27 -0600 Subject: [PATCH] perf(pareto): skip already-dominated points in pareto_front MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pareto_front` re-scanned every candidate from scratch. Track a `dominated` bitset instead: whenever `i`'s scan finds `i` dominates `j`, mark `j` so the outer loop skips `j` outright when it reaches it. The inner check now reads both directions of `pareto_compare` — the objective scan already computes both flags, so this is ~free. Bit-identical, including under NaN-intransitive dominance: a mark is only ever set from a direct pairwise `pareto_compare` result, never inferred transitively. Also strict-or-neutral on work — the marks can only ever let the outer loop *skip*, never add a scan. Whole-program callgrind Ir for the compare_profile benchmark: 169,440,644,233 -> 165,311,562,939 (-2.44%); `pareto_front` self-Ir 44.1B -> 39.9B. --- src/pareto/front.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/pareto/front.rs b/src/pareto/front.rs index 716ced5..1441a17 100644 --- a/src/pareto/front.rs +++ b/src/pareto/front.rs @@ -55,8 +55,19 @@ pub fn pareto_front( oriented.extend_from_slice(&objectives.as_minimization(&c.evaluation.objectives)); } + // `dominated[j]` is set the moment some candidate is found to dominate + // `j`. Whenever `i`'s scan finds `i` dominates `j`, mark `j` so the + // outer loop can skip `j` entirely when it reaches it. This never does + // more work than the plain scan — the marks only ever let us *skip* — + // and it stays bit-identical even under NaN-intransitive dominance: + // a mark is set only from a direct pairwise `pareto_compare` result, + // never inferred transitively. + let mut dominated: Vec = vec![false; n]; let mut out = Vec::new(); 'outer: for i in 0..n { + if dominated[i] { + continue 'outer; + } let ai_feasible = feasible[i]; let ai_violation = violation[i]; let ai = &oriented[i * m..i * m + m]; @@ -64,13 +75,13 @@ pub fn pareto_front( if i == j { continue; } - // `i` is kept only if no `j` dominates it — i.e. no `j` for which - // `pareto_compare(a_i, a_j)` would be `DominatedBy`. This inlines - // exactly that one outcome of `pareto_compare`. - let dominated_by_j = match (ai_feasible, feasible[j]) { - (true, false) => false, - (false, true) => true, - (false, false) => ai_violation > violation[j], + // Inline both directions of `pareto_compare`: `j` dominating + // `i` excludes `i`; `i` dominating `j` lets us skip `j`'s own + // scan later. + let (i_dominates_j, j_dominates_i) = match (ai_feasible, feasible[j]) { + (true, false) => (true, false), + (false, true) => (false, true), + (false, false) => (ai_violation < violation[j], ai_violation > violation[j]), (true, true) => { let aj = &oriented[j * m..j * m + m]; let mut a_better_anywhere = false; @@ -84,12 +95,18 @@ pub fn pareto_front( b_better_anywhere = true; } } - b_better_anywhere && !a_better_anywhere + ( + a_better_anywhere && !b_better_anywhere, + b_better_anywhere && !a_better_anywhere, + ) } }; - if dominated_by_j { + if j_dominates_i { continue 'outer; } + if i_dominates_j { + dominated[j] = true; + } } out.push(population[i].clone()); }