evaluate: use rayon par_sort_by for parallel LLM comparisons

Merge sort parallelizes naturally — multiple LLM comparison calls
happen concurrently. Safe because merge sort terminates correctly
even with non-deterministic comparators (unlike quicksort).

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-03-14 19:27:28 -04:00
parent e12dea503b
commit 433d36aea8

View file

@ -3,6 +3,7 @@
use crate::store;
use crate::store::StoreView;
use crate::agents::llm;
use std::sync::atomic::{AtomicUsize, Ordering};
pub fn cmd_consolidate_batch(count: usize, auto: bool, agent: Option<String>) -> Result<(), String> {
let store = store::Store::load()?;
@ -178,17 +179,18 @@ pub fn cmd_evaluate_agents(samples_per_type: usize, model: &str) -> Result<(), S
all_samples.len() * (all_samples.len() as f64).log2() as usize,
model);
// Sort with LLM comparator — yes, really. Rust's sort_by with an
// LLM as the comparison function. Each comparison is an API call.
let mut comparisons = 0usize;
all_samples.sort_by(|a, b| {
comparisons += 1;
if comparisons % 10 == 0 {
eprint!(" {} comparisons...\r", comparisons);
// Sort with LLM comparator — yes, really. Rayon's parallel merge sort
// with an LLM as the comparison function. Multiple API calls in parallel.
let comparisons = AtomicUsize::new(0);
use rayon::slice::ParallelSliceMut;
all_samples.par_sort_by(|a, b| {
let n = comparisons.fetch_add(1, Ordering::Relaxed);
if n % 10 == 0 {
eprint!(" {} comparisons...\r", n);
}
llm_compare(a, b, model).unwrap_or(std::cmp::Ordering::Equal)
});
eprintln!(" {} total comparisons", comparisons);
eprintln!(" {} total comparisons", comparisons.load(Ordering::Relaxed));
let sorted = all_samples;