From 6085f5df2618450a0316e4712e6c51689fb0c444 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Tue, 31 Jan 2023 15:07:02 -0600 Subject: [PATCH] rayon --- assignment-1/Cargo.lock | 97 ++++++++++++++++++++++++++++++++++++++++ assignment-1/Cargo.toml | 1 + assignment-1/src/main.rs | 63 ++++++++++++++------------ 3 files changed, 132 insertions(+), 29 deletions(-) diff --git a/assignment-1/Cargo.lock b/assignment-1/Cargo.lock index 5da292b..012c9ed 100644 --- a/assignment-1/Cargo.lock +++ b/assignment-1/Cargo.lock @@ -17,6 +17,7 @@ dependencies = [ "itertools", "num", "ordered-float", + "rayon", ] [[package]] @@ -37,6 +38,12 @@ version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.1.4" @@ -74,6 +81,49 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + [[package]] name = "either" version = "1.8.1" @@ -159,6 +209,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "num" version = "0.4.0" @@ -238,6 +297,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -301,6 +370,28 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "rustix" version = "0.36.7" @@ -315,6 +406,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.152" diff --git a/assignment-1/Cargo.toml b/assignment-1/Cargo.toml index 8ddbc92..f3d800b 100644 --- a/assignment-1/Cargo.toml +++ b/assignment-1/Cargo.toml @@ -11,3 +11,4 @@ clap = { version = "4.1.4", features = ["derive"] } itertools = "0.10.5" num = { version = "0.4.0", features = ["serde"] } ordered-float = "3.4.0" +rayon = "1.6.1" diff --git a/assignment-1/src/main.rs b/assignment-1/src/main.rs index be49e50..06540f6 100644 --- a/assignment-1/src/main.rs +++ b/assignment-1/src/main.rs @@ -15,8 +15,9 @@ use anyhow::Result; use clap::Parser; use itertools::Itertools; use ordered_float::NotNan; +use rayon::prelude::{IntoParallelIterator, ParallelIterator}; -use crate::image::{Image, Pixel}; +use crate::image::Image; use crate::input_file::parse_input_file; use crate::ray::Ray; use crate::scene_data::Object; @@ -98,40 +99,44 @@ fn main() -> Result<()> { } }; + // This is an L because par_bridge is unordered + let pixels = (0..scene.image_width) + .cartesian_product(0..scene.image_height) + .collect_vec(); + // Loop through every single pixel of the output file - let mut pixels = - vec![Pixel::default(); scene.image_width * scene.image_width]; - for (px, py) in - (0..scene.image_width).cartesian_product(0..scene.image_height) - { - let pixel_in_space = pixel_translation(px, py); - let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space); + let pixels = pixels + .into_par_iter() + .map(|(px, py)| { + let pixel_in_space = pixel_translation(px, py); + let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space); - let earliest_intersection = scene - .objects - .iter() - .filter_map(|object| { - let sphere = match object { - Object::Sphere(v) => v, - _ => return None, /* TODO: Handle other object types for - * intersection as well */ - }; + let earliest_intersection = scene + .objects + .iter() + .filter_map(|object| { + let sphere = match object { + Object::Sphere(v) => v, + _ => return None, /* TODO: Handle other object types for + * intersection as well */ + }; - ray.intersects_at(sphere).map(|t| (t, sphere)) - }) - .min_by_key(|(t, _)| NotNan::new(*t).unwrap()); + ray.intersects_at(sphere).map(|t| (t, sphere)) + }) + .min_by_key(|(t, _)| NotNan::new(*t).unwrap()); - let pixel_color = match earliest_intersection { - Some((_, sphere)) => scene.material_colors[sphere.material], - // There was no intersection, so this should default to the background - // color - None => scene.bkg_color, - }; + let pixel_color = match earliest_intersection { + Some((_, sphere)) => scene.material_colors[sphere.material], + // There was no intersection, so this should default to the background + // color + None => scene.bkg_color, + }; - // println!("({px}, {py}): {intersection:?}\t{ray:?} {sphere:?}"); + // println!("({px}, {py}): {intersection:?}\t{ray:?} {sphere:?}"); - pixels[py * scene.image_height + px] = pixel_color.to_pixel(); - } + pixel_color.to_pixel() + }) + .collect::>(); let image = Image { width: scene.image_width,