// cargo bench use rand::distributions::{Distribution, Uniform}; use crossbeam; const NTHREADS: usize = 8; fn random_vec(length: usize) -> Vec { let step = Uniform::new_inclusive(1, 100); let mut rng = rand::thread_rng(); step.sample_iter(&mut rng).take(length).collect() } fn main() { let numbers = random_vec(1_000); println!("global sum via threads : {}", parallel_sum(&numbers)); println!("global sum single-threaded: {}", sequential_sum(&numbers)); } fn parallel_sum(numbers: &[i32]) -> i32 { let num_tasks_per_thread = numbers.len() / NTHREADS; crossbeam::scope(|scope| { // The `collect` is important to eagerly start the threads! let threads: Vec<_> = numbers .chunks(num_tasks_per_thread) .map(|chunk| scope.spawn(move |_| chunk.iter().cloned().sum::())) .collect(); let thread_sum: i32 = threads.into_iter().map(|t| t.join().unwrap()).sum(); return thread_sum; }).unwrap() } fn sequential_sum(numbers: &[i32]) -> i32 { let num_tasks_per_thread = numbers.len() / NTHREADS; crossbeam::scope(|scope| { // The `collect` is important to eagerly start the threads! let _threads: Vec<_> = numbers .chunks(num_tasks_per_thread) .map(|chunk| scope.spawn(move |_| chunk.iter().cloned().sum::())) .collect(); let no_thread_sum: i32 = numbers.iter().cloned().sum(); return no_thread_sum; }).unwrap() } #[cfg(test)] mod tests { extern crate test; use super::*; use test::Bencher; #[bench] fn bench_sequential(b: &mut Bencher) { let numbers = random_vec(10_000_000); b.iter(|| sequential_sum(&numbers)); } #[bench] fn bench_parallel(b: &mut Bencher) { let numbers = random_vec(10_000_000); b.iter(|| parallel_sum(&numbers)); } }