use std::error::Error;
use std::fmt;
use std::sync::OnceLock;
pub const DEFAULT_PARALLEL_PARTITIONS: usize = 8;
static PARALLEL_PARTITIONS: OnceLock<usize> = OnceLock::new();
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ParallelismError {
ZeroPartitions,
AlreadyInitialized { configured: usize },
}
impl fmt::Display for ParallelismError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ZeroPartitions => formatter.write_str("PiP parallel partitions must be positive"),
Self::AlreadyInitialized { configured } => write!(
formatter,
"PiP parallel partitions are already fixed at {configured}"
),
}
}
}
impl Error for ParallelismError {}
pub fn set_parallel_partitions(partitions: usize) -> Result<(), ParallelismError> {
if partitions == 0 {
return Err(ParallelismError::ZeroPartitions);
}
PARALLEL_PARTITIONS
.set(partitions)
.map_err(|_| ParallelismError::AlreadyInitialized {
configured: parallel_partitions(),
})
}
pub fn parallel_partitions() -> usize {
*PARALLEL_PARTITIONS.get_or_init(|| DEFAULT_PARALLEL_PARTITIONS)
}
#[inline]
pub(crate) fn parallel_chunk_len(work_units: usize) -> Option<usize> {
(work_units > 0).then(|| work_units.div_ceil(parallel_partitions().min(work_units)))
}
#[inline]
pub(crate) fn lanes_per_job(active_lanes: usize) -> usize {
active_lanes.div_ceil(parallel_partitions().min(active_lanes))
}