功能说明
该示例用 Rayon 的并行迭代器把一个顺序的“映射并求和”变成多线程执行。par_iter 自动把工作切分到线程池,各线程以工作窃取平衡负载;结果与顺序版本完全一致,因此可并行化而不改变语义。另一个函数对可变切片就地并行转换,填充顺序由调用方保证。
关键代码
导入 prelude 后,切片获得 par_iter 与 par_iter_mut 等并行适配器,接口与顺序迭代器基本相同。求和用 saturating_mul 避免溢出恐慌,并把结果归约。就地转换用 for_each 写入每个槽位,checked_mul 在溢出时保留原值,避免未定义行为。测试用一千个数比较并行与顺序结果,确保并行化没有引入差异。
使用注意
并行化只在工作足够重、元素足够多时才划算:对极小的切片,线程调度与切分开销会超过收益。闭包必须是线程安全的,共享可变状态需用同步原语,否则编译期即会拒绝。工作窃取依赖任务粒度,粒度过粗会让某个线程成为瓶颈,可用 with_min_len 调整切分下限。并行不改变语义,但改变了执行顺序,含副作用的闭包必须自行保证可交换。
代码示例
use rayon::prelude::*;
/// Sum of squares, computed across all available worker threads.
pub fn sum_of_squares(values: &[i64]) -> i64 {
values.par_iter().map(|value| value.saturating_mul(*value)).sum()
}
/// Transform each element in place, preserving order in the result.
pub fn transform(value: &mut [i64], factor: i64) {
value.par_iter_mut().for_each(|slot| {
*slot = slot.checked_mul(factor).unwrap_or(*slot);
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn squares_match_sequential() {
let data: Vec<i64> = (1..=1000).collect();
let expected: i64 = data.iter().map(|v| v * v).sum();
assert_eq!(sum_of_squares(&data), expected);
}
}