use crate::compute::AdaptiveContext;
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum Parallelism {
Auto {
threshold: usize,
},
ForceParallel,
Serial,
}
impl Parallelism {
pub const DEFAULT_THRESHOLD: usize = 1024;
#[allow(dead_code)]
#[inline]
pub fn should_parallelize(self, len: usize) -> bool {
match self {
Self::Serial => false,
Self::ForceParallel => true,
Self::Auto { threshold } => len >= threshold,
}
}
#[inline]
pub fn effective_threshold(self, ctx: &AdaptiveContext) -> usize {
ctx.apply_threshold(self)
}
#[inline]
pub fn should_parallelize_adaptive(self, len: usize, ctx: &AdaptiveContext) -> bool {
match self {
Self::Serial => false,
Self::ForceParallel => true,
Self::Auto { .. } => len >= self.effective_threshold(ctx),
}
}
#[inline]
pub fn should_parallelize_current(self, len: usize) -> bool {
self.should_parallelize_adaptive(len, &crate::compute::current_adaptive_context())
}
}
impl Default for Parallelism {
fn default() -> Self {
Self::Auto {
threshold: Self::DEFAULT_THRESHOLD,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::compute::AdaptiveContext;
#[test]
fn auto_below_threshold_is_serial() {
assert!(!Parallelism::Auto { threshold: 10 }.should_parallelize(9));
}
#[test]
fn auto_at_threshold_is_parallel() {
assert!(Parallelism::Auto { threshold: 10 }.should_parallelize(10));
}
#[test]
fn force_parallel_always() {
assert!(Parallelism::ForceParallel.should_parallelize(0));
}
#[test]
fn serial_never() {
assert!(!Parallelism::Serial.should_parallelize(usize::MAX));
}
#[test]
fn default_is_auto_1024() {
assert_eq!(
Parallelism::default(),
Parallelism::Auto { threshold: 1024 }
);
}
#[test]
fn adaptive_lowers_threshold_under_headroom() {
let ctx = AdaptiveContext {
admission_budget: 8,
parallelism_threshold: 256,
rayon_threads: 8,
};
assert!(Parallelism::default().should_parallelize_adaptive(300, &ctx));
assert!(!Parallelism::default().should_parallelize_adaptive(100, &ctx));
}
}