diff --git a/Cargo.lock b/Cargo.lock index 5d946c5..d3000da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ name = "mandelbrot" version = "0.2.0" dependencies = [ - "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -22,11 +22,6 @@ name = "color_quant" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crossbeam" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "deque" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index ed9d067..5a6b3bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,4 @@ authors = ["Jim Blandy "] [dependencies] num = "0.1.34" image = "0.10.1" -crossbeam = "0.2.9" +rayon = "0.4.0" diff --git a/src/main.rs b/src/main.rs index 31de28a..5881f5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -144,10 +144,10 @@ fn measure_elapsed_time(f: F) -> Duration { } -extern crate crossbeam; +extern crate rayon; -use std::sync::Mutex; use std::io::Write; +use rayon::prelude::*; fn main() { let args : Vec = std::env::args().collect(); @@ -172,47 +172,25 @@ fn main() { let mut pixels = vec![0; bounds.0 * bounds.1]; - for threads in [1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 20, 30, 40, 50, 60, 70, 80, 90, - //100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 - ].iter() { - let band_rows = bounds.1 / 400; - - let dt = measure_elapsed_time(|| { - let bands = Mutex::new(pixels.chunks_mut(band_rows * bounds.0).enumerate()); - crossbeam::scope(|scope| { - for i in 0..*threads { - scope.spawn(|| { - let mut count = 0; - loop { - match { - let mut guard = bands.lock().unwrap(); - guard.next() - } - { - None => { return; } - Some((i, band)) => { - count += 1; - let top = band_rows * i; - let height = band.len() / bounds.0; - let band_bounds = (bounds.0, height); - let band_upper_left = pixel_to_point(bounds, (0, top), - upper_left, lower_right); - let band_lower_right = pixel_to_point(bounds, (bounds.0, top + height), - upper_left, lower_right); - render(band, band_bounds, band_upper_left, band_lower_right); - } - } - } - }); - } + // Scope of slicing up `pixels` into horizontal bands. + { + let bands: Vec<(usize, &mut [u8])> = pixels + .chunks_mut(bounds.0) + .enumerate() + .collect(); + + bands.into_par_iter() + .weight_max() + .for_each(|(i, band)| { + let top = i; + let band_bounds = (bounds.0, 1); + let band_upper_left = pixel_to_point(bounds, (0, top), + upper_left, lower_right); + let band_lower_right = pixel_to_point(bounds, (bounds.0, top + 1), + upper_left, lower_right); + render(band, band_bounds, band_upper_left, band_lower_right); }); - }); - println!("{:4} {:.3}", - threads, - dt.as_secs() as f64 + dt.subsec_nanos() as f64 * 1e-9); } - write_bitmap(&args[1], &pixels[..], bounds).expect("error writing PNG file"); + write_bitmap(&args[1], &pixels, bounds).expect("error writing PNG file"); }