// cargo bench
use rand::distributions::{Distribution, Uniform};
use crossbeam;
const NTHREADS: usize = 8;
fn random_vec(length: usize) -> Vec<i32> {
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::<i32>()))
.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::<i32>()))
.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));
}
}
Comments