diff --git a/Cargo.lock b/Cargo.lock index 170a7f3e5edd54afa809a2874a2b364d4d9b7d7f..61cde7f161b7c4177cb781addeb2f484af3b7477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1493,6 +1493,7 @@ version = "0.1.0" dependencies = [ "async-std", "clap", + "criterion", "hercules_rt", "juno_build", "nom 8.0.0", diff --git a/juno_samples/rodinia/srad/Cargo.toml b/juno_samples/rodinia/srad/Cargo.toml index e41a8871d3694045d42206028d56c429698e41fc..facf8c3bc7c92fe0b77dd85900c3e53307d358e5 100644 --- a/juno_samples/rodinia/srad/Cargo.toml +++ b/juno_samples/rodinia/srad/Cargo.toml @@ -8,6 +8,9 @@ edition = "2021" name = "juno_srad" path = "src/main.rs" +[lib] +path = "src/lib.rs" + [features] cuda = ["juno_build/cuda", "hercules_rt/cuda"] @@ -21,3 +24,10 @@ async-std = "*" clap = { version = "*", features = ["derive"] } with_builtin_macros = "0.1.0" nom = "*" + +[dev-dependencies] +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "srad_bench" +harness = false diff --git a/juno_samples/rodinia/srad/benches/srad_bench.rs b/juno_samples/rodinia/srad/benches/srad_bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..d327454002a6f9cabe4c40f74098570ea0d22d66 --- /dev/null +++ b/juno_samples/rodinia/srad/benches/srad_bench.rs @@ -0,0 +1,62 @@ +#![feature(concat_idents)] +use criterion::{criterion_group, criterion_main, Criterion}; + +use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo}; + +juno_build::juno!("srad"); + +use juno_srad::*; + +fn srad_bench(c: &mut Criterion) { + let mut group = c.benchmark_group("srad bench"); + + let mut r = runner!(srad); + let niter = 100; + let lambda = 0.5; + let nrows = 502; + let ncols = 458; + let image = "data/image.pgm".to_string(); + let Image { + image: image_ori, + max, + rows: image_ori_rows, + cols: image_ori_cols, + } = read_graphics(image); + let image = resize(&image_ori, image_ori_rows, image_ori_cols, nrows, ncols); + let mut image_h = HerculesMutBox::from(image.clone()); + let mut iN = (0..nrows).map(|i| i as i32 - 1).collect::<Vec<_>>(); + let mut iS = (0..nrows).map(|i| i as i32 + 1).collect::<Vec<_>>(); + let mut jW = (0..ncols).map(|j| j as i32 - 1).collect::<Vec<_>>(); + let mut jE = (0..ncols).map(|j| j as i32 + 1).collect::<Vec<_>>(); + // Fix boundary conditions + iN[0] = 0; + iS[nrows - 1] = (nrows - 1) as i32; + jW[0] = 0; + jE[ncols - 1] = (ncols - 1) as i32; + let iN_h = HerculesImmBox::from(iN.as_slice()); + let iS_h = HerculesImmBox::from(iS.as_slice()); + let jW_h = HerculesImmBox::from(jW.as_slice()); + let jE_h = HerculesImmBox::from(jE.as_slice()); + group.bench_function("srad bench", |b| { + b.iter(|| { + async_std::task::block_on(async { + r.run( + nrows as u64, + ncols as u64, + niter as u64, + image_h.to(), + iN_h.to(), + iS_h.to(), + jW_h.to(), + jE_h.to(), + max, + lambda, + ) + .await + }); + }) + }); +} + +criterion_group!(benches, srad_bench); +criterion_main!(benches); diff --git a/juno_samples/rodinia/srad/src/lib.rs b/juno_samples/rodinia/srad/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d63660070ff0f61d47057ea00b14b3fb31db6e09 --- /dev/null +++ b/juno_samples/rodinia/srad/src/lib.rs @@ -0,0 +1,123 @@ +#![feature(concat_idents)] +mod graphics; +mod rust_srad; + +pub use graphics::*; + +use clap::Parser; + +use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo}; + +juno_build::juno!("srad"); + +#[derive(Parser)] +#[clap(author, version, about, long_about = None)] +pub struct SRADInputs { + pub niter: usize, + pub lambda: f32, + pub nrows: usize, + pub ncols: usize, + pub image: String, + #[clap(short, long)] + pub output: Option<String>, + #[clap(short, long)] + pub verify: bool, + #[clap(long = "output-verify", value_name = "PATH")] + pub output_verify: Option<String>, +} + +pub fn srad_harness(args: SRADInputs) { + async_std::task::block_on(async { + let SRADInputs { + niter, + lambda, + nrows, + ncols, + image, + output, + verify, + output_verify, + } = args; + + let Image { + image: image_ori, + max, + rows: image_ori_rows, + cols: image_ori_cols, + } = read_graphics(image); + let image = resize(&image_ori, image_ori_rows, image_ori_cols, nrows, ncols); + let mut image_h = HerculesMutBox::from(image.clone()); + + let mut iN = (0..nrows).map(|i| i as i32 - 1).collect::<Vec<_>>(); + let mut iS = (0..nrows).map(|i| i as i32 + 1).collect::<Vec<_>>(); + let mut jW = (0..ncols).map(|j| j as i32 - 1).collect::<Vec<_>>(); + let mut jE = (0..ncols).map(|j| j as i32 + 1).collect::<Vec<_>>(); + + // Fix boundary conditions + iN[0] = 0; + iS[nrows - 1] = (nrows - 1) as i32; + jW[0] = 0; + jE[ncols - 1] = (ncols - 1) as i32; + + let iN_h = HerculesImmBox::from(iN.as_slice()); + let iS_h = HerculesImmBox::from(iS.as_slice()); + let jW_h = HerculesImmBox::from(jW.as_slice()); + let jE_h = HerculesImmBox::from(jE.as_slice()); + + let mut runner = runner!(srad); + let result: Vec<f32> = HerculesMutBox::from( + runner + .run( + nrows as u64, + ncols as u64, + niter as u64, + image_h.to(), + iN_h.to(), + iS_h.to(), + jW_h.to(), + jE_h.to(), + max, + lambda, + ) + .await, + ) + .as_slice() + .to_vec(); + + if let Some(output) = output { + write_graphics(output, &result, nrows, ncols, max); + } + + if verify { + let mut rust_result = image; + rust_srad::srad( + nrows, + ncols, + niter, + &mut rust_result, + &iN, + &iS, + &jW, + &jE, + max, + lambda, + ); + + if let Some(output) = output_verify { + write_graphics(output, &rust_result, nrows, ncols, max); + } + + let max_diff = result + .iter() + .zip(rust_result.iter()) + .map(|(a, b)| (*a as i32 - *b as i32).abs()) + .max() + .unwrap_or(0); + assert!( + max_diff <= 1, + "Verification failed: maximum pixel difference of {} exceeds threshold of 1", + max_diff + ); + } + }) +} diff --git a/juno_samples/rodinia/srad/src/main.rs b/juno_samples/rodinia/srad/src/main.rs index 1b99b41aada5341fb3157cfb0d97be3a99e73796..87d1e7e8504584478f51ac2b9dc20dbc04716c81 100644 --- a/juno_samples/rodinia/srad/src/main.rs +++ b/juno_samples/rodinia/srad/src/main.rs @@ -1,126 +1,6 @@ -#![feature(concat_idents)] -mod graphics; -mod rust_srad; - -use graphics::*; - use clap::Parser; -use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo}; - -juno_build::juno!("srad"); - -#[derive(Parser)] -#[clap(author, version, about, long_about = None)] -struct SRADInputs { - niter: usize, - lambda: f32, - nrows: usize, - ncols: usize, - image: String, - #[clap(short, long)] - output: Option<String>, - #[clap(short, long)] - verify: bool, - #[clap(long = "output-verify", value_name = "PATH")] - output_verify: Option<String>, -} - -fn srad_harness(args: SRADInputs) { - async_std::task::block_on(async { - let SRADInputs { - niter, - lambda, - nrows, - ncols, - image, - output, - verify, - output_verify, - } = args; - - let Image { - image: image_ori, - max, - rows: image_ori_rows, - cols: image_ori_cols, - } = read_graphics(image); - let image = resize(&image_ori, image_ori_rows, image_ori_cols, nrows, ncols); - let mut image_h = HerculesMutBox::from(image.clone()); - - let mut iN = (0..nrows).map(|i| i as i32 - 1).collect::<Vec<_>>(); - let mut iS = (0..nrows).map(|i| i as i32 + 1).collect::<Vec<_>>(); - let mut jW = (0..ncols).map(|j| j as i32 - 1).collect::<Vec<_>>(); - let mut jE = (0..ncols).map(|j| j as i32 + 1).collect::<Vec<_>>(); - - // Fix boundary conditions - iN[0] = 0; - iS[nrows - 1] = (nrows - 1) as i32; - jW[0] = 0; - jE[ncols - 1] = (ncols - 1) as i32; - - let iN_h = HerculesImmBox::from(iN.as_slice()); - let iS_h = HerculesImmBox::from(iS.as_slice()); - let jW_h = HerculesImmBox::from(jW.as_slice()); - let jE_h = HerculesImmBox::from(jE.as_slice()); - - let mut runner = runner!(srad); - let result: Vec<f32> = HerculesMutBox::from( - runner - .run( - nrows as u64, - ncols as u64, - niter as u64, - image_h.to(), - iN_h.to(), - iS_h.to(), - jW_h.to(), - jE_h.to(), - max, - lambda, - ) - .await, - ) - .as_slice() - .to_vec(); - - if let Some(output) = output { - write_graphics(output, &result, nrows, ncols, max); - } - - if verify { - let mut rust_result = image; - rust_srad::srad( - nrows, - ncols, - niter, - &mut rust_result, - &iN, - &iS, - &jW, - &jE, - max, - lambda, - ); - - if let Some(output) = output_verify { - write_graphics(output, &rust_result, nrows, ncols, max); - } - - let max_diff = result - .iter() - .zip(rust_result.iter()) - .map(|(a, b)| (*a as i32 - *b as i32).abs()) - .max() - .unwrap_or(0); - assert!( - max_diff <= 1, - "Verification failed: maximum pixel difference of {} exceeds threshold of 1", - max_diff - ); - } - }) -} +use juno_srad::*; fn main() { let args = SRADInputs::parse();