Use Rayon to render each row of pixels as a separate task, processed by Rayon's built-in thread pool.

pull/4/head
Jason Orendorff 8 years ago
parent 292638561a
commit 55095fc4f5

7
Cargo.lock generated

@ -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"

@ -6,4 +6,4 @@ authors = ["Jim Blandy <jimb@red-bean.com>"]
[dependencies]
num = "0.1.34"
image = "0.10.1"
crossbeam = "0.2.9"
rayon = "0.4.0"

@ -144,10 +144,10 @@ fn measure_elapsed_time<F: FnOnce()>(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<String> = 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");
}

Loading…
Cancel
Save