From 66b4d9fa6b24d2e3ca380a52a0b8c559a91cd005 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 14 May 2026 12:22:38 -0600 Subject: [PATCH] perf(age_moea): score only the splitting front in environmental_selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `prox` and `nearest` were computed for every member of `combined`, but the scoring loop only ever reads the entries for the splitting front (`remaining`). Fill just those, skipping the `lp_norm` / `lp_distance` work — and the `powf` calls inside them — for the rest of `combined`. Bit-identical: the skipped entries were never read. In the compare_profile benchmark this cut `pow` + its libm kernel from ~16.2B to ~14.3B Ir and `environmental_selection` self-Ir from 2.13B to 1.82B. Round 3 whole-program: 173,803,642,945 -> 169,440,644,233 (-2.51%). --- src/algorithms/age_moea.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/algorithms/age_moea.rs b/src/algorithms/age_moea.rs index 29fbbe6..35a9f1e 100644 --- a/src/algorithms/age_moea.rs +++ b/src/algorithms/age_moea.rs @@ -306,12 +306,17 @@ fn environmental_selection( // once per (remaining, pick) pair instead of per (remaining, all-keep). let mut keep = selected.clone(); let mut remaining: Vec = splitting.clone(); - let prox: Vec = (0..combined.len()) - .map(|i| lp_norm(&translated[i], p)) - .collect(); - let mut nearest: Vec = (0..combined.len()) - .map(|i| nearest_neighbor_distance(i, &translated, &keep, p)) - .collect(); + // `prox` and `nearest` are only ever read for splitting-front members + // (the `remaining` set) — the scoring loop never touches the entries + // for `selected` or discarded members. Filling only the `remaining` + // entries skips `lp_norm` / `lp_distance` work on the rest of + // `combined`; bit-identical, since those entries were never used. + let mut prox: Vec = vec![0.0; combined.len()]; + let mut nearest: Vec = vec![f64::INFINITY; combined.len()]; + for &i in &remaining { + prox[i] = lp_norm(&translated[i], p); + nearest[i] = nearest_neighbor_distance(i, &translated, &keep, p); + } while keep.len() < n { // Pick the remaining candidate with the largest score. let mut best_idx: Option = None;