From f3c074c24c89e6393d8de26aacc4d7e9a6796cbb Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Fri, 24 Apr 2026 13:54:47 +0200 Subject: [PATCH] feat(history): parallel learning_curves under rayon feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-slice posterior collection runs in parallel via par_iter; merge into the per-key HashMap is sequential in slice order so iteration order and HashMap insertion order are identical to the sequential impl. Preserves deterministic output across thread counts. Default-feature (no rayon) build unchanged — uses the T2 sequential impl. Part of T3. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/history.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/history.rs b/src/history.rs index 5191929..920469c 100644 --- a/src/history.rs +++ b/src/history.rs @@ -262,17 +262,45 @@ impl, O: Observer, K: Eq + Hash + Clone> History HashMap> { - let mut data: HashMap> = HashMap::new(); - for slice in &self.time_slices { - for (idx, skill) in slice.skills.iter() { - if let Some(key) = self.keys.key(idx).cloned() { - data.entry(key) - .or_default() - .push((slice.time, skill.posterior())); + #[cfg(feature = "rayon")] + { + use rayon::prelude::*; + + let per_slice: Vec> = self + .time_slices + .par_iter() + .map(|ts| { + ts.skills + .iter() + .map(|(idx, sk)| (idx, ts.time, sk.posterior())) + .collect() + }) + .collect(); + + let mut data: HashMap> = HashMap::new(); + for slice_contrib in per_slice { + for (idx, t, g) in slice_contrib { + if let Some(key) = self.keys.key(idx).cloned() { + data.entry(key).or_default().push((t, g)); + } } } + data + } + #[cfg(not(feature = "rayon"))] + { + let mut data: HashMap> = HashMap::new(); + for slice in &self.time_slices { + for (idx, skill) in slice.skills.iter() { + if let Some(key) = self.keys.key(idx).cloned() { + data.entry(key) + .or_default() + .push((slice.time, skill.posterior())); + } + } + } + data } - data } /// Skill estimate at the latest time slice the competitor appears in.