diff --git a/Cargo.lock b/Cargo.lock index 1973fbbeb88622cb01fe3ddfc191aae796a00f54..ebe621e801437e1d3512943a39df7382fa578f72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,6 +1338,7 @@ version = "0.1.0" dependencies = [ "async-std", "clap", + "criterion", "hercules_rt", "juno_build", "opencv", diff --git a/juno_samples/edge_detection/Cargo.toml b/juno_samples/edge_detection/Cargo.toml index bd2ae5c9d375faa56d847cc40cb21c9028dca780..fc5fb451f277897cd3fa5004f953380ee2ed2f46 100644 --- a/juno_samples/edge_detection/Cargo.toml +++ b/juno_samples/edge_detection/Cargo.toml @@ -27,3 +27,10 @@ async-std = "*" clap = { version = "*", features = ["derive"] } with_builtin_macros = "0.1.0" opencv = { version = "*", features = ["clang-runtime"], optional = true } + +[dev-dependencies] +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "edge_detection_bench" +harness = false diff --git a/juno_samples/edge_detection/benches/edge_detection_bench.rs b/juno_samples/edge_detection/benches/edge_detection_bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..f7f004109e84ade2ac0ce1f49efb45ea4a2466f7 --- /dev/null +++ b/juno_samples/edge_detection/benches/edge_detection_bench.rs @@ -0,0 +1,102 @@ +#![feature(concat_idents)] +use std::slice::from_raw_parts; + +use criterion::{criterion_group, criterion_main, Criterion}; + +use opencv::core::{Mat, Size, CV_32F, CV_8U}; +use opencv::imgproc::{cvt_color_def, ColorConversionCodes}; +use opencv::prelude::{MatTraitConst, VideoCaptureTrait, VideoCaptureTraitConst}; +use opencv::videoio::{VideoCapture, VideoCaptureProperties, VideoWriter, VideoWriterTrait}; + +use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo}; + +use juno_edge_detection::*; + +juno_build::juno!("edge_detection"); + +fn edge_detection_bench(c: &mut Criterion) { + let mut group = c.benchmark_group("edge detection bench"); + group.sample_size(10); + + let input = "examples/formula1_scaled.mp4"; + + let gs: usize = 7; + let gaussian_filter: Vec<f32> = vec![ + 0.000036, 0.000363, 0.001446, 0.002291, 0.001446, 0.000363, 0.000036, 0.000363, 0.003676, + 0.014662, 0.023226, 0.014662, 0.003676, 0.000363, 0.001446, 0.014662, 0.058488, 0.092651, + 0.058488, 0.014662, 0.001446, 0.002291, 0.023226, 0.092651, 0.146768, 0.092651, 0.023226, + 0.002291, 0.001446, 0.014662, 0.058488, 0.092651, 0.058488, 0.014662, 0.001446, 0.000363, + 0.003676, 0.014662, 0.023226, 0.014662, 0.003676, 0.000363, 0.000036, 0.000363, 0.001446, + 0.002291, 0.001446, 0.000363, 0.000036, + ]; + let gaussian_filter_h = HerculesImmBox::from(gaussian_filter.as_slice()); + + let sz: usize = 3; + let structure: Vec<f32> = vec![1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; + let structure_h = HerculesImmBox::from(structure.as_slice()); + + let sb: usize = 3; + let sx: Vec<f32> = vec![-1.0, 0.0, 1.0, -2.0, 0.0, 2.0, -1.0, 0.0, 1.0]; + let sx_h = HerculesImmBox::from(sx.as_slice()); + + let sy: Vec<f32> = vec![-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0]; + let sy_h = HerculesImmBox::from(sy.as_slice()); + + let theta: f32 = 0.1; + + let mut video = VideoCapture::from_file_def(&input).expect("Error loading video"); + assert!(video.is_opened().unwrap()); + + let fps = video + .get(VideoCaptureProperties::CAP_PROP_FPS.into()) + .expect("Error getting fps"); + + let _num_frames = video + .get(VideoCaptureProperties::CAP_PROP_FRAME_COUNT.into()) + .expect("Error getting number of frames") as usize; + let width = video + .get(VideoCaptureProperties::CAP_PROP_FRAME_WIDTH.into()) + .expect("Error getting width") as usize; + let height = video + .get(VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT.into()) + .expect("Error getting height") as usize; + let num_frames = 5; + + let mut r = runner!(edge_detection); + + group.bench_function("edge detection bench", |b| { + b.iter(|| { + for i in 0..num_frames { + let frame = load_frame(&mut video); + let ptr = frame.ptr_def().unwrap() as *const f32; + + assert!(frame.rows() as usize == height); + assert!(frame.cols() as usize == width); + + let input = unsafe { from_raw_parts(ptr, height * width) }; + + let input_h = HerculesImmBox::from(input); + + let result = async_std::task::block_on(async { + r.run( + height as u64, + width as u64, + gs as u64, + sz as u64, + sb as u64, + input_h.to(), + gaussian_filter_h.to(), + structure_h.to(), + sx_h.to(), + sy_h.to(), + theta, + ) + .await + }); + } + }) + }); +} + +criterion_group!(benches, edge_detection_bench); +criterion_main!(benches); diff --git a/juno_samples/edge_detection/src/lib.rs b/juno_samples/edge_detection/src/lib.rs index f675d5f52f6dec5651bf0d8cd5fafddb268c538c..37268b561f2c0104a89f097b88abde5d3a34692a 100644 --- a/juno_samples/edge_detection/src/lib.rs +++ b/juno_samples/edge_detection/src/lib.rs @@ -34,7 +34,7 @@ pub struct EdgeDetectionInputs { pub frames: Option<usize>, } -fn load_frame(video: &mut VideoCapture) -> Mat { +pub fn load_frame(video: &mut VideoCapture) -> Mat { let mut frame = Mat::default(); let Ok(true) = video.read(&mut frame) else { @@ -67,7 +67,7 @@ fn load_frame(video: &mut VideoCapture) -> Mat { result } -fn frame_from_slice(frame: &[f32], height: usize, width: usize) -> Mat { +pub fn frame_from_slice(frame: &[f32], height: usize, width: usize) -> Mat { let result = Mat::from_slice(frame) .expect("Failed to create matrix from result") .reshape(1, height as i32)