Parallel Map with Scoped Threads
Map slices in chunks with std::thread::scope, join worker results in order, and avoid unsafe shared mutable state.
Code
use std::thread;
fn parallel_map<T, U, F>(items: &[T], workers: usize, transform: F) -> Vec<U>
where
T: Sync,
U: Send,
F: Fn(&T) -> U + Sync,
{
assert!(workers > 0, "workers must be positive");
let chunk_size = items.len().div_ceil(workers).max(1);
let mut results = Vec::with_capacity(items.len());
thread::scope(|scope| {
let mut handles = Vec::new();
for chunk in items.chunks(chunk_size) {
let transform = &transform;
handles.push(scope.spawn(move || {
chunk.iter().map(|item| transform(item)).collect::<Vec<U>>()
}));
}
for handle in handles {
results.extend(handle.join().expect("worker panicked"));
}
});
results
}
fn main() {
let numbers: Vec<u64> = (1..=10).collect();
let squares = parallel_map(&numbers, 3, |number| number * number);
println!("{squares:?}");
assert_eq!(squares, vec![1, 4, 9, 16, 25, 36, 49, 64, 81, 100]);
let empty: Vec<u64> = parallel_map(&[] as &[u64], 4, |number| number + 1);
assert!(empty.is_empty());
let words = ["a", "bb", "ccc"];
let lengths = parallel_map(&words, 8, |word| word.len());
assert_eq!(lengths, vec![1, 2, 3]);
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.