diff --git a/Cargo.toml b/Cargo.toml index 1fa1c2758..f5eb9f205 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -163,7 +163,7 @@ encase = { version = "0.12", optional = true } serde_json = "1.0" rand_xorshift = "0.4" rand_isaac = "0.4" -criterion = { version = "0.4", features = ["html_reports"] } +criterion = { version = "0.7", features = ["html_reports"] } nalgebra = { path = ".", features = ["debug", "compare", "rand", "macros"] } # For matrix comparison macro @@ -195,6 +195,7 @@ required-features = ["rand"] [profile.bench] lto = true +codegen-units = 1 [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs diff --git a/benches/common/macros.rs b/benches/common/macros.rs index 2f64f83a1..a7f8848c2 100644 --- a/benches/common/macros.rs +++ b/benches/common/macros.rs @@ -1,16 +1,24 @@ #![macro_use] +/// This will call `Drop::drop()` within the benchmarking loop for all arguments that were not consumed +/// by the binary operation. +/// +/// Do not use this macro for types with non-trivial `Drop` implementation unless you want to include it +/// into the measurement. macro_rules! bench_binop( ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let a = rng.random::<$t1>(); - let b = rng.random::<$t2>(); - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - a.$binop(b) - })); + bh.bench_function(stringify!($name), |bh| bh.iter_batched( + || (rng.random::<$t1>(), rng.random::<$t2>()), + |args| { + args.0.$binop(args.1) + }, + criterion::BatchSize::SmallInput), + ); } } ); @@ -19,50 +27,63 @@ macro_rules! bench_binop_ref( ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let a = rng.random::<$t1>(); - let b = rng.random::<$t2>(); - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - a.$binop(&b) - })); + bh.bench_function(stringify!($name), |bh| bh.iter_batched_ref( + || (rng.random::<$t1>(), rng.random::<$t2>()), + |args| { + args.0.$binop(&args.1) + }, + criterion::BatchSize::SmallInput), + ); } } ); -macro_rules! bench_binop_fn( - ($name: ident, $t1: ty, $t2: ty, $binop: path) => { +/// This will call `Drop::drop()` within the benchmarking loop for all arguments that were not consumed +/// by the binary operation. +/// +/// Do not use this macro for types with non-trivial `Drop` implementation unless you want to include it +/// into the measurement. +macro_rules! bench_binop_single_1st( + ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; + use std::hint::black_box; + let mut rng = IsaacRng::seed_from_u64(0); - let a = rng.random::<$t1>(); - let b = rng.random::<$t2>(); - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - $binop(&a, &b) - })); + let first = black_box(rng.random::<$t1>()); + + bh.bench_function(stringify!($name), |bh| bh.iter_batched( + || rng.random::<$t2>(), + |second| { + first.$binop(second) + }, + criterion::BatchSize::SmallInput), + ); } } ); -macro_rules! bench_unop_na( - ($name: ident, $t: ty, $unop: ident) => { +macro_rules! bench_binop_single_1st_ref( + ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { fn $name(bh: &mut criterion::Criterion) { - const LEN: usize = 1 << 13; - use rand::SeedableRng; - let mut rng = IsaacRng::seed_from_u64(0); + use std::hint::black_box; - let elems: Vec<$t> = (0usize .. LEN).map(|_| rng.random::<$t>()).collect(); - let mut i = 0; + let mut rng = IsaacRng::seed_from_u64(0); - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - i = (i + 1) & (LEN - 1); + let first = black_box(rng.random::<$t1>()); - unsafe { - std::hint::black_box(na::$unop(elems.get_unchecked(i))) - } - })); + bh.bench_function(stringify!($name), |bh| bh.iter_batched_ref( + || rng.random::<$t2>(), + |second| { + first.$binop(second) + }, + criterion::BatchSize::SmallInput), + ); } } ); @@ -70,44 +91,17 @@ macro_rules! bench_unop_na( macro_rules! bench_unop( ($name: ident, $t: ty, $unop: ident) => { fn $name(bh: &mut criterion::Criterion) { - const LEN: usize = 1 << 13; - use rand::SeedableRng; - let mut rng = IsaacRng::seed_from_u64(0); - let mut elems: Vec<$t> = (0usize .. LEN).map(|_| rng.random::<$t>()).collect(); - let mut i = 0; - - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - i = (i + 1) & (LEN - 1); - - unsafe { - std::hint::black_box(elems.get_unchecked_mut(i).$unop()) - } - })); - } - } -); - -macro_rules! bench_construction( - ($name: ident, $constructor: path, $( $args: ident: $types: ty),*) => { - fn $name(bh: &mut criterion::Criterion) { - const LEN: usize = 1 << 13; - - use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); - $(let $args: Vec<$types> = (0usize .. LEN).map(|_| rng.random::<$types>()).collect();)* - let mut i = 0; - - bh.bench_function(stringify!($name), move |bh| bh.iter(|| { - i = (i + 1) & (LEN - 1); - - unsafe { - let res = $constructor($(*$args.get_unchecked(i),)*); - std::hint::black_box(res) - } - })); + bh.bench_function(stringify!($name), |bh| bh.iter_batched_ref( + || rng.random::<$t>(), + |arg| { + arg.$unop() + }, + criterion::BatchSize::SmallInput), + ); } } ); diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs index 2f156ca72..b58e9cecb 100644 --- a/benches/core/matrix.rs +++ b/benches/core/matrix.rs @@ -1,6 +1,7 @@ use na::{DMatrix, DVector, Matrix2, Matrix3, Matrix4, OMatrix, U10, Vector2, Vector3, Vector4}; use rand::Rng; use rand_isaac::IsaacRng; +use std::hint::black_box; use std::ops::{Add, Div, Mul, Sub}; #[path = "../common/macros.rs"] @@ -26,10 +27,18 @@ bench_binop!(mat2_mul_v, Matrix2, Vector2, mul); bench_binop!(mat3_mul_v, Matrix3, Vector3, mul); bench_binop!(mat4_mul_v, Matrix4, Vector4, mul); +bench_binop_single_1st!(single_mat2_mul_v, Matrix2, Vector2, mul); +bench_binop_single_1st!(single_mat3_mul_v, Matrix3, Vector3, mul); +bench_binop_single_1st!(single_mat4_mul_v, Matrix4, Vector4, mul); + bench_binop_ref!(mat2_tr_mul_v, Matrix2, Vector2, tr_mul); bench_binop_ref!(mat3_tr_mul_v, Matrix3, Vector3, tr_mul); bench_binop_ref!(mat4_tr_mul_v, Matrix4, Vector4, tr_mul); +bench_binop_single_1st_ref!(single_mat2_tr_mul_v, Matrix2, Vector2, tr_mul); +bench_binop_single_1st_ref!(single_mat3_tr_mul_v, Matrix3, Vector3, tr_mul); +bench_binop_single_1st_ref!(single_mat4_tr_mul_v, Matrix4, Vector4, tr_mul); + bench_binop!(mat2_mul_s, Matrix2, f32, mul); bench_binop!(mat3_mul_s, Matrix3, f32, mul); bench_binop!(mat4_mul_s, Matrix4, f32, mul); @@ -47,171 +56,309 @@ bench_unop!(mat3_transpose, Matrix3, transpose); bench_unop!(mat4_transpose, Matrix4, transpose); fn mat_div_scalar(b: &mut criterion::Criterion) { - let a = DMatrix::from_row_slice(1000, 1000, &vec![2.0; 1000000]); - let n = 42.0; - - b.bench_function("mat_div_scalar", move |bh| { - bh.iter(|| { - let mut aa = a.clone(); - let mut b = aa.view_mut((0, 0), (1000, 1000)); - b /= n - }) + b.bench_function("mat_div_scalar", |bh| { + bh.iter_batched( + || { + ( + DMatrix::from_row_slice(1000, 1000, &vec![2.0; 1000000]), + 42.0, + ) + }, + |(mut a, n)| { + let mut b = a.view_mut((0, 0), (1000, 1000)); + b /= n; + a + }, + criterion::BatchSize::SmallInput, + ) }); } fn mat100_add_mat100(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(100, 100); - let b = DMatrix::::new_random(100, 100); - - bench.bench_function("mat100_add_mat100", move |bh| bh.iter(|| &a + &b)); + bench.bench_function("mat100_add_mat100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DMatrix::::new_random(100, 100), + ) + }, + |args| (&args.0) + (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat4_mul_mat4(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(4, 4); - let b = DMatrix::::new_random(4, 4); - - bench.bench_function("mat4_mul_mat4", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat4_mul_mat4", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(4, 4), + DMatrix::::new_random(4, 4), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat5_mul_mat5(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(5, 5); - let b = DMatrix::::new_random(5, 5); - - bench.bench_function("mat5_mul_mat5", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat5_mul_mat5", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(5, 5), + DMatrix::::new_random(5, 5), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat6_mul_mat6(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(6, 6); - let b = DMatrix::::new_random(6, 6); - - bench.bench_function("mat6_mul_mat6", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat6_mul_mat6", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(6, 6), + DMatrix::::new_random(6, 6), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat7_mul_mat7(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(7, 7); - let b = DMatrix::::new_random(7, 7); - - bench.bench_function("mat7_mul_mat7", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat7_mul_mat7", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(7, 7), + DMatrix::::new_random(7, 7), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat8_mul_mat8(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(8, 8); - let b = DMatrix::::new_random(8, 8); - - bench.bench_function("mat8_mul_mat8", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat8_mul_mat8", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(8, 8), + DMatrix::::new_random(8, 8), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat9_mul_mat9(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(9, 9); - let b = DMatrix::::new_random(9, 9); - - bench.bench_function("mat9_mul_mat9", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat9_mul_mat9", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(9, 9), + DMatrix::::new_random(9, 9), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat10_mul_mat10(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(10, 10); - let b = DMatrix::::new_random(10, 10); - - bench.bench_function("mat10_mul_mat10", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat10_mul_mat10", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(10, 10), + DMatrix::::new_random(10, 10), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat10_mul_mat10_static(bench: &mut criterion::Criterion) { - let a = OMatrix::::new_random(); - let b = OMatrix::::new_random(); - - bench.bench_function("mat10_mul_mat10_static", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat10_mul_mat10_static", |bh| { + bh.iter_batched_ref( + || { + ( + OMatrix::::new_random(), + OMatrix::::new_random(), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat100_mul_mat100(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(100, 100); - let b = DMatrix::::new_random(100, 100); - - bench.bench_function("mat100_mul_mat100", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat100_mul_mat100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DMatrix::::new_random(100, 100), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn mat500_mul_mat500(bench: &mut criterion::Criterion) { - let a = DMatrix::::from_element(500, 500, 5f64); - let b = DMatrix::::from_element(500, 500, 6f64); - - bench.bench_function("mat500_mul_mat500", move |bh| bh.iter(|| &a * &b)); + bench.bench_function("mat500_mul_mat500", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(500, 500), + DMatrix::::new_random(500, 500), + ) + }, + |args| (&args.0) * (&args.1), + criterion::BatchSize::SmallInput, + ) + }); } fn iter(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(1000, 1000); - - bench.bench_function("iter", move |bh| { - bh.iter(|| { - for value in a.iter() { - std::hint::black_box(value); - } - }) + bench.bench_function("iter", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(1000, 1000), + |a| { + for value in a.iter() { + black_box(value); + } + }, + criterion::BatchSize::SmallInput, + ) }); } fn iter_rev(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(1000, 1000); - - bench.bench_function("iter_rev", move |bh| { - bh.iter(|| { - for value in a.iter().rev() { - std::hint::black_box(value); - } - }) + bench.bench_function("iter_rev", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(1000, 1000), + |a| { + for value in a.iter().rev() { + black_box(value); + } + }, + criterion::BatchSize::SmallInput, + ) }); } fn copy_from(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(1000, 1000); - let mut b = DMatrix::::new_random(1000, 1000); - - bench.bench_function("copy_from", move |bh| { - bh.iter(|| { - b.copy_from(&a); - }) + bench.bench_function("copy_from", |bh| { + bh.iter_batched( + || { + ( + DMatrix::::new_random(1000, 1000), + DMatrix::::new_random(1000, 1000), + ) + }, + |(a, mut b)| { + b.copy_from(&a); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn axpy(bench: &mut criterion::Criterion) { - let x = DVector::::from_element(100000, 2.0); - let mut y = DVector::::from_element(100000, 3.0); - let a = 42.0; - - bench.bench_function("axpy", move |bh| { - bh.iter(|| { - y.axpy(a, &x, 1.0); - }) + bench.bench_function("axpy", |bh| { + bh.iter_batched( + || { + ( + DVector::::new_random(100000), + DVector::::new_random(100000), + rand::random(), + ) + }, + |(x, mut y, a)| { + y.axpy(a, &x, 1.0); + (x, y) + }, + criterion::BatchSize::SmallInput, + ) }); } fn tr_mul_to(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(1000, 1000); - let b = DVector::::new_random(1000); - let mut c = DVector::from_element(1000, 0.0); - - bench.bench_function("tr_mul_to", move |bh| bh.iter(|| a.tr_mul_to(&b, &mut c))); + bench.bench_function("tr_mul_to", |bh| { + bh.iter_batched( + || { + ( + DMatrix::::new_random(1000, 1000), + DVector::::new_random(1000), + DVector::from_element(1000, 0.0), + ) + }, + |(a, b, mut c)| { + a.tr_mul_to(&b, &mut c); + (a, b, c) + }, + criterion::BatchSize::SmallInput, + ) + }); } -fn mat_mul_mat(bench: &mut criterion::Criterion) { - let a = DMatrix::::new_random(100, 100); - let b = DMatrix::::new_random(100, 100); - let mut ab = DMatrix::::from_element(100, 100, 0.0); - - bench.bench_function("mat_mul_mat", move |bh| { - bh.iter(|| { - std::hint::black_box(a.mul_to(&b, &mut ab)); - }) +fn mat_mul_mat_to(bench: &mut criterion::Criterion) { + bench.bench_function("mat_mul_mat_to", |bh| { + bh.iter_batched( + || { + ( + DMatrix::::new_random(100, 100), + DMatrix::::new_random(100, 100), + DMatrix::::from_element(100, 100, 0.0), + ) + }, + |(a, b, mut ab)| { + a.mul_to(&b, &mut ab); + (a, b, ab) + }, + criterion::BatchSize::SmallInput, + ) }); } fn mat100_from_fn(bench: &mut criterion::Criterion) { bench.bench_function("mat100_from_fn", move |bh| { - bh.iter(|| DMatrix::from_fn(100, 100, |a, b| a + b)) + bh.iter(|| { + DMatrix::from_fn(black_box(100), black_box(100), |a, b| { + black_box(a) + black_box(b) + }) + }) }); } fn mat500_from_fn(bench: &mut criterion::Criterion) { bench.bench_function("mat500_from_fn", move |bh| { - bh.iter(|| DMatrix::from_fn(500, 500, |a, b| a + b)) + bh.iter(|| { + DMatrix::from_fn(black_box(500), black_box(500), |a, b| { + black_box(a) + black_box(b) + }) + }) }); } @@ -232,9 +379,15 @@ criterion_group!( mat2_mul_v, mat3_mul_v, mat4_mul_v, + single_mat2_mul_v, + single_mat3_mul_v, + single_mat4_mul_v, mat2_tr_mul_v, mat3_tr_mul_v, mat4_tr_mul_v, + single_mat2_tr_mul_v, + single_mat3_tr_mul_v, + single_mat4_tr_mul_v, mat2_mul_s, mat3_mul_s, mat4_mul_s, @@ -264,7 +417,7 @@ criterion_group!( copy_from, axpy, tr_mul_to, - mat_mul_mat, + mat_mul_mat_to, mat100_from_fn, mat500_from_fn, ); diff --git a/benches/core/vector.rs b/benches/core/vector.rs index f05789e74..6f4714263 100644 --- a/benches/core/vector.rs +++ b/benches/core/vector.rs @@ -1,6 +1,7 @@ use na::{DVector, SVector, Vector2, Vector3, Vector4}; use rand::Rng; use rand_isaac::IsaacRng; + use std::ops::{Add, Div, Mul, Sub}; #[path = "../common/macros.rs"] @@ -49,81 +50,144 @@ bench_binop_ref!(vec10000_dot_f32, SVector, SVector, dot fn vec10000_axpy_f64(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let mut a = DVector::new_random(10000); - let b = DVector::new_random(10000); - let n = rng.random::(); - bh.bench_function("vec10000_axpy_f64", move |bh| { - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("vec10000_axpy_f64", |bh| { + bh.iter_batched( + || { + ( + DVector::new_random(10000), + DVector::new_random(10000), + rng.random::(), + ) + }, + |(mut a, b, n)| { + a.axpy(n, &b, 1.0); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn vec10000_axpy_beta_f64(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let mut a = DVector::new_random(10000); - let b = DVector::new_random(10000); - let n = rng.random::(); - let beta = rng.random::(); - bh.bench_function("vec10000_axpy_beta_f64", move |bh| { - bh.iter(|| a.axpy(n, &b, beta)) + bh.bench_function("vec10000_axpy_beta_f64", |bh| { + bh.iter_batched( + || { + ( + DVector::new_random(10000), + DVector::new_random(10000), + rng.random::(), + rng.random::(), + ) + }, + |(mut a, b, n, beta)| { + a.axpy(n, &b, beta); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn vec10000_axpy_f64_slice(bh: &mut criterion::Criterion) { use rand::SeedableRng; - let mut rng = IsaacRng::seed_from_u64(0); - let mut a = DVector::new_random(10000); - let b = DVector::new_random(10000); - let n = rng.random::(); - bh.bench_function("vec10000_axpy_f64_slice", move |bh| { - bh.iter(|| { - let mut a = a.fixed_rows_mut::<10000>(0); - let b = b.fixed_rows::<10000>(0); + let mut rng = IsaacRng::seed_from_u64(0); - a.axpy(n, &b, 1.0) - }) + bh.bench_function("vec10000_axpy_f64_slice", |bh| { + bh.iter_batched( + || { + ( + DVector::new_random(10000), + DVector::new_random(10000), + rng.random::(), + ) + }, + |(mut a, b, n)| { + let mut a_slice = a.fixed_rows_mut::<10000>(0); + let b_slice = b.fixed_rows::<10000>(0); + a_slice.axpy(n, &b_slice, 1.0); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn vec10000_axpy_f64_static(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let mut a = SVector::::new_random(); - let b = SVector::::new_random(); - let n = rng.random::(); // NOTE: for some reasons, it is much faster if the argument are boxed (Box::new(OVector...)). - bh.bench_function("vec10000_axpy_f64_static", move |bh| { - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("vec10000_axpy_f64_static", |bh| { + bh.iter_batched( + || { + ( + SVector::::new_random(), + SVector::::new_random(), + rng.random::(), + ) + }, + |(mut a, b, n)| { + a.axpy(n, &b, 1.0); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn vec10000_axpy_f32(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let mut a = DVector::new_random(10000); - let b = DVector::new_random(10000); - let n = rng.random::(); - bh.bench_function("vec10000_axpy_f32", move |bh| { - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("vec10000_axpy_f32", |bh| { + bh.iter_batched( + || { + ( + DVector::new_random(10000), + DVector::new_random(10000), + rng.random::(), + ) + }, + |(mut a, b, n)| { + a.axpy(n, &b, 1.0); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn vec10000_axpy_beta_f32(bh: &mut criterion::Criterion) { use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); - let mut a = DVector::new_random(10000); - let b = DVector::new_random(10000); - let n = rng.random::(); - let beta = rng.random::(); - bh.bench_function("vec10000_axpy_beta_f32", move |bh| { - bh.iter(|| a.axpy(n, &b, beta)) + bh.bench_function("vec10000_axpy_beta_f32", |bh| { + bh.iter_batched( + || { + ( + DVector::new_random(10000), + DVector::new_random(10000), + rng.random::(), + rng.random::(), + ) + }, + |(mut a, b, n, beta)| { + a.axpy(n, &b, beta); + (a, b) + }, + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/geometry/quaternion.rs b/benches/geometry/quaternion.rs index 37c29c01e..90a841e33 100644 --- a/benches/geometry/quaternion.rs +++ b/benches/geometry/quaternion.rs @@ -16,6 +16,12 @@ bench_binop!( Vector3, mul ); +bench_binop_single_1st!( + single_unit_quaternion_mul_v, + UnitQuaternion, + Vector3, + mul +); bench_binop!(quaternion_mul_s, Quaternion, f32, mul); bench_binop!(quaternion_div_s, Quaternion, f32, div); @@ -23,8 +29,8 @@ bench_binop!(quaternion_div_s, Quaternion, f32, div); bench_unop!(quaternion_inv, Quaternion, try_inverse); bench_unop!(unit_quaternion_inv, UnitQuaternion, inverse); -// bench_unop_self!(quaternion_conjugate, Quaternion, conjugate); -// bench_unop!(quaternion_normalize, Quaternion, normalize); +bench_unop!(quaternion_conjugate, Quaternion, conjugate); +bench_unop!(quaternion_normalize, Quaternion, normalize); criterion_group!( quaternion, @@ -32,8 +38,11 @@ criterion_group!( quaternion_sub_q, quaternion_mul_q, unit_quaternion_mul_v, + single_unit_quaternion_mul_v, quaternion_mul_s, quaternion_div_s, quaternion_inv, - unit_quaternion_inv + unit_quaternion_inv, + quaternion_conjugate, + quaternion_normalize, ); diff --git a/benches/lib.rs b/benches/lib.rs index df866cca3..7342b4428 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -6,14 +6,27 @@ extern crate rand_package as rand; #[macro_use] extern crate criterion; -use na::DMatrix; +use na::{DMatrix, SMatrix, Scalar}; use rand::Rng; +use rand::distr::{Distribution, StandardUniform}; use rand_isaac::IsaacRng; pub mod core; pub mod geometry; pub mod linalg; +#[allow(dead_code)] +fn reproducible_smatrix() -> SMatrix +where + T: Scalar, + StandardUniform: Distribution, +{ + use rand::SeedableRng; + let mut rng = IsaacRng::seed_from_u64(0); + SMatrix::from_fn(|_, _| rng.random()) +} + +#[allow(dead_code)] fn reproducible_dmatrix(nrows: usize, ncols: usize) -> DMatrix { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); diff --git a/benches/linalg/bidiagonal.rs b/benches/linalg/bidiagonal.rs index b45b1ac03..af99f2bda 100644 --- a/benches/linalg/bidiagonal.rs +++ b/benches/linalg/bidiagonal.rs @@ -5,61 +5,82 @@ mod macros; // Without unpack. fn bidiagonalize_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("bidiagonalize_100x100", move |bh| { - bh.iter(|| std::hint::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| Bidiagonal::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn bidiagonalize_100x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 500); - bh.bench_function("bidiagonalize_100x500", move |bh| { - bh.iter(|| std::hint::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_100x500", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 500), + |m| Bidiagonal::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn bidiagonalize_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("bidiagonalize_4x4", move |bh| { - bh.iter(|| std::hint::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_4x4", |bh| { + bh.iter_batched( + || Matrix4::::new_random(), + |m| Bidiagonal::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn bidiagonalize_500x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 100); - bh.bench_function("bidiagonalize_500x100", move |bh| { - bh.iter(|| std::hint::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_500x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(500, 100), + |m| Bidiagonal::new(m), + criterion::BatchSize::SmallInput, + ) }); } // With unpack. fn bidiagonalize_unpack_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("bidiagonalize_unpack_100x100", move |bh| { - bh.iter(|| { - let bidiag = Bidiagonal::new(m.clone()); - let _ = bidiag.unpack(); - }) + bh.bench_function("bidiagonalize_unpack_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| { + let bidiag = Bidiagonal::new(m); + bidiag.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn bidiagonalize_unpack_100x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 500); - bh.bench_function("bidiagonalize_unpack_100x500", move |bh| { - bh.iter(|| { - let bidiag = Bidiagonal::new(m.clone()); - let _ = bidiag.unpack(); - }) + bh.bench_function("bidiagonalize_unpack_100x500", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 500), + |m| { + let bidiag = Bidiagonal::new(m); + bidiag.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn bidiagonalize_unpack_500x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 100); - bh.bench_function("bidiagonalize_unpack_500x100", move |bh| { - bh.iter(|| { - let bidiag = Bidiagonal::new(m.clone()); - let _ = bidiag.unpack(); - }) + bh.bench_function("bidiagonalize_unpack_500x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(500, 100), + |m| { + let bidiag = Bidiagonal::new(m); + bidiag.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/cholesky.rs b/benches/linalg/cholesky.rs index 09c806423..a40f1c03b 100644 --- a/benches/linalg/cholesky.rs +++ b/benches/linalg/cholesky.rs @@ -1,119 +1,142 @@ use na::{Cholesky, DMatrix, DVector}; -fn cholesky_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let m = &m * m.transpose(); +fn random_positive_definite_dmatrix(nrows: usize, ncols: usize) -> DMatrix { + // @note(geo-ant) to get positive definite matrices we use M*M^T + alpha*I, + // where alpha is a constant that is chosen so that the eigenvales stay + // positive. + let m = DMatrix::::new_random(nrows, ncols); + let alpha = f64::EPSILON.sqrt() * m.norm_squared(); + let nrows = m.nrows(); + &m * m.transpose() + alpha * DMatrix::identity(nrows, nrows) +} - bh.bench_function("cholesky_100x100", move |bh| { - bh.iter(|| std::hint::black_box(Cholesky::new(m.clone()))) +fn cholesky_100x100(bh: &mut criterion::Criterion) { + bh.bench_function("cholesky_100x100", |bh| { + bh.iter_batched( + || random_positive_definite_dmatrix(100, 100), + |m| Cholesky::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_500x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 500); - let m = &m * m.transpose(); - - bh.bench_function("cholesky_500x500", move |bh| { - bh.iter(|| std::hint::black_box(Cholesky::new(m.clone()))) + bh.bench_function("cholesky_500x500", |bh| { + bh.iter_batched( + || random_positive_definite_dmatrix(500, 500), + |m| Cholesky::new(m), + criterion::BatchSize::SmallInput, + ) }); } // With unpack. fn cholesky_decompose_unpack_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let m = &m * m.transpose(); - - bh.bench_function("cholesky_decompose_unpack_100x100", move |bh| { - bh.iter(|| { - let chol = Cholesky::new(m.clone()).unwrap(); - let _ = chol.unpack(); - }) + bh.bench_function("cholesky_decompose_unpack_100x100", |bh| { + bh.iter_batched( + || random_positive_definite_dmatrix(100, 100), + |m| { + let chol = Cholesky::new(m).unwrap(); + chol.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_decompose_unpack_500x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 500); - let m = &m * m.transpose(); - - bh.bench_function("cholesky_decompose_unpack_500x500", move |bh| { - bh.iter(|| { - let chol = Cholesky::new(m.clone()).unwrap(); - let _ = chol.unpack(); - }) + bh.bench_function("cholesky_decompose_unpack_500x500", |bh| { + bh.iter_batched( + || random_positive_definite_dmatrix(500, 500), + |m| { + let chol = Cholesky::new(m).unwrap(); + chol.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_solve_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let m = &m * m.transpose(); - let v = DVector::::new_random(10); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_solve_10x10", move |bh| { - bh.iter(|| { - let _ = chol.solve(&v); - }) + bh.bench_function("cholesky_solve_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(10, 10); + let v = DVector::::new_random(10); + let chol = Cholesky::new(m).unwrap(); + (chol, v) + }, + |(chol, v)| chol.solve(v), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_solve_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let m = &m * m.transpose(); - let v = DVector::::new_random(100); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_solve_100x100", move |bh| { - bh.iter(|| { - let _ = chol.solve(&v); - }) + bh.bench_function("cholesky_solve_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(100, 100); + let v = DVector::::new_random(100); + let chol = Cholesky::new(m).unwrap(); + (chol, v) + }, + |(chol, v)| chol.solve(v), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_solve_500x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 500); - let m = &m * m.transpose(); - let v = DVector::::new_random(500); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_solve_500x500", move |bh| { - bh.iter(|| { - let _ = chol.solve(&v); - }) + bh.bench_function("cholesky_solve_500x500", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(500, 500); + let v = DVector::::new_random(500); + let chol = Cholesky::new(m).unwrap(); + (chol, v) + }, + |(chol, v)| chol.solve(v), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_inverse_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let m = &m * m.transpose(); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_inverse_10x10", move |bh| { - bh.iter(|| { - let _ = chol.inverse(); - }) + bh.bench_function("cholesky_inverse_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(10, 10); + Cholesky::new(m).unwrap() + }, + |chol| chol.inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_inverse_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let m = &m * m.transpose(); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_inverse_100x100", move |bh| { - bh.iter(|| { - let _ = chol.inverse(); - }) + bh.bench_function("cholesky_inverse_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(100, 100); + Cholesky::new(m).unwrap() + }, + |chol| chol.inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn cholesky_inverse_500x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 500); - let m = &m * m.transpose(); - let chol = Cholesky::new(m.clone()).unwrap(); - - bh.bench_function("cholesky_inverse_500x500", move |bh| { - bh.iter(|| { - let _ = chol.inverse(); - }) + bh.bench_function("cholesky_inverse_500x500", |bh| { + bh.iter_batched_ref( + || { + let m = random_positive_definite_dmatrix(500, 500); + Cholesky::new(m).unwrap() + }, + |chol| chol.inverse(), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/full_piv_lu.rs b/benches/linalg/full_piv_lu.rs index 9b3abd31b..0c98a04b2 100644 --- a/benches/linalg/full_piv_lu.rs +++ b/benches/linalg/full_piv_lu.rs @@ -2,78 +2,106 @@ use na::{DMatrix, DVector, FullPivLU}; // Without unpack. fn full_piv_lu_decompose_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - bh.bench_function("full_piv_lu_decompose_10x10", move |bh| { - bh.iter(|| std::hint::black_box(FullPivLU::new(m.clone()))) + bh.bench_function("full_piv_lu_decompose_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| FullPivLU::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_decompose_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("full_piv_lu_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(FullPivLU::new(m.clone()))) + bh.bench_function("full_piv_lu_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| FullPivLU::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_solve_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_solve_10x10", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(10, 1.0); - lu.solve_mut(&mut b); - b - }) + bh.bench_function("full_piv_lu_solve_10x10", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(10, 10); + (FullPivLU::new(m), DVector::::new_random(10)) + }, + |(lu, mut b)| { + lu.solve_mut(&mut b); + (lu, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_solve_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_solve_100x100", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(100, 1.0); - lu.solve_mut(&mut b); - b - }) + bh.bench_function("full_piv_lu_solve_100x100", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(100, 100); + (FullPivLU::new(m), DVector::::new_random(100)) + }, + |(lu, mut b)| { + lu.solve_mut(&mut b); + (lu, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_inverse_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_inverse_10x10", move |bh| { - bh.iter(|| std::hint::black_box(lu.try_inverse())) + bh.bench_function("full_piv_lu_inverse_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(10, 10); + FullPivLU::new(m) + }, + |lu| lu.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_inverse_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_inverse_100x100", move |bh| { - bh.iter(|| std::hint::black_box(lu.try_inverse())) + bh.bench_function("full_piv_lu_inverse_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(100, 100); + FullPivLU::new(m) + }, + |lu| lu.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_determinant_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_determinant_10x10", move |bh| { - bh.iter(|| std::hint::black_box(lu.determinant())) + bh.bench_function("full_piv_lu_determinant_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(10, 10); + FullPivLU::new(m) + }, + |lu| lu.determinant(), + criterion::BatchSize::SmallInput, + ) }); } fn full_piv_lu_determinant_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = FullPivLU::new(m.clone()); - - bh.bench_function("full_piv_lu_determinant_100x100", move |bh| { - bh.iter(|| std::hint::black_box(lu.determinant())) + bh.bench_function("full_piv_lu_determinant_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(100, 100); + FullPivLU::new(m) + }, + |lu| lu.determinant(), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/hessenberg.rs b/benches/linalg/hessenberg.rs index 0610748af..9572c052b 100644 --- a/benches/linalg/hessenberg.rs +++ b/benches/linalg/hessenberg.rs @@ -5,44 +5,59 @@ mod macros; // Without unpack. fn hessenberg_decompose_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("hessenberg_decompose_4x4", move |bh| { - bh.iter(|| std::hint::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_4x4", |bh| { + bh.iter_batched( + || Matrix4::::new_random(), + |m| Hessenberg::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn hessenberg_decompose_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("hessenberg_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| Hessenberg::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn hessenberg_decompose_200x200(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(200, 200); - bh.bench_function("hessenberg_decompose_200x200", move |bh| { - bh.iter(|| std::hint::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| Hessenberg::new(m), + criterion::BatchSize::SmallInput, + ) }); } // With unpack. fn hessenberg_decompose_unpack_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("hessenberg_decompose_unpack_100x100", move |bh| { - bh.iter(|| { - let hess = Hessenberg::new(m.clone()); - let _ = hess.unpack(); - }) + bh.bench_function("hessenberg_decompose_unpack_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| { + let hess = Hessenberg::new(m); + hess.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn hessenberg_decompose_unpack_200x200(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(200, 200); - bh.bench_function("hessenberg_decompose_unpack_200x200", move |bh| { - bh.iter(|| { - let hess = Hessenberg::new(m.clone()); - let _ = hess.unpack(); - }) + bh.bench_function("hessenberg_decompose_unpack_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| { + let hess = Hessenberg::new(m); + hess.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/lu.rs b/benches/linalg/lu.rs index 30177d94f..7e7847909 100644 --- a/benches/linalg/lu.rs +++ b/benches/linalg/lu.rs @@ -2,78 +2,106 @@ use na::{DMatrix, DVector, LU}; // Without unpack. fn lu_decompose_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - bh.bench_function("lu_decompose_10x10", move |bh| { - bh.iter(|| std::hint::black_box(LU::new(m.clone()))) + bh.bench_function("lu_decompose_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| LU::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn lu_decompose_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("lu_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(LU::new(m.clone()))) + bh.bench_function("lu_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| LU::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn lu_solve_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_solve_10x10", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(10, 1.0); - lu.solve_mut(&mut b); - b - }) + bh.bench_function("lu_solve_10x10", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(10, 10); + (LU::new(m), DVector::::new_random(10)) + }, + |(lu, mut b)| { + lu.solve_mut(&mut b); + (lu, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn lu_solve_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_solve_100x100", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(100, 1.0); - lu.solve_mut(&mut b); - b - }) + bh.bench_function("lu_solve_100x100", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(100, 100); + (LU::new(m), DVector::::new_random(100)) + }, + |(lu, mut b)| { + lu.solve_mut(&mut b); + (lu, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn lu_inverse_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_inverse_10x10", move |bh| { - bh.iter(|| std::hint::black_box(lu.try_inverse())) + bh.bench_function("lu_inverse_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(10, 10); + LU::new(m) + }, + |lu| lu.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn lu_inverse_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_inverse_100x100", move |bh| { - bh.iter(|| std::hint::black_box(lu.try_inverse())) + bh.bench_function("lu_inverse_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(100, 100); + LU::new(m) + }, + |lu| lu.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn lu_determinant_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_determinant_10x10", move |bh| { - bh.iter(|| std::hint::black_box(lu.determinant())) + bh.bench_function("lu_determinant_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(10, 10); + LU::new(m) + }, + |lu| lu.determinant(), + criterion::BatchSize::SmallInput, + ) }); } fn lu_determinant_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let lu = LU::new(m.clone()); - - bh.bench_function("lu_determinant_100x100", move |bh| { - bh.iter(|| std::hint::black_box(lu.determinant())) + bh.bench_function("lu_determinant_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(100, 100); + LU::new(m) + }, + |lu| lu.determinant(), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/qr.rs b/benches/linalg/qr.rs index ed28e869d..7f67ccd6a 100644 --- a/benches/linalg/qr.rs +++ b/benches/linalg/qr.rs @@ -5,105 +5,140 @@ mod macros; // Without unpack. fn qr_decompose_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("qr_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| QR::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn qr_decompose_100x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 500); - bh.bench_function("qr_decompose_100x500", move |bh| { - bh.iter(|| std::hint::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_100x500", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 500), + |m| QR::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn qr_decompose_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("qr_decompose_4x4", move |bh| { - bh.iter(|| std::hint::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_4x4", |bh| { + bh.iter_batched( + || Matrix4::::new_random(), + |m| QR::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn qr_decompose_500x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 100); - bh.bench_function("qr_decompose_500x100", move |bh| { - bh.iter(|| std::hint::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_500x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(500, 100), + |m| QR::new(m), + criterion::BatchSize::SmallInput, + ) }); } // With unpack. fn qr_decompose_unpack_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - bh.bench_function("qr_decompose_unpack_100x100", move |bh| { - bh.iter(|| { - let qr = QR::new(m.clone()); - let _ = qr.unpack(); - }) + bh.bench_function("qr_decompose_unpack_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| { + let qr = QR::new(m); + qr.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn qr_decompose_unpack_100x500(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 500); - bh.bench_function("qr_decompose_unpack_100x500", move |bh| { - bh.iter(|| { - let qr = QR::new(m.clone()); - let _ = qr.unpack(); - }) + bh.bench_function("qr_decompose_unpack_100x500", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 500), + |m| { + let qr = QR::new(m); + qr.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn qr_decompose_unpack_500x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(500, 100); - bh.bench_function("qr_decompose_unpack_500x100", move |bh| { - bh.iter(|| { - let qr = QR::new(m.clone()); - let _ = qr.unpack(); - }) + bh.bench_function("qr_decompose_unpack_500x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(500, 100), + |m| { + let qr = QR::new(m); + qr.unpack() + }, + criterion::BatchSize::SmallInput, + ) }); } fn qr_solve_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let qr = QR::new(m.clone()); - - bh.bench_function("qr_solve_10x10", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(10, 1.0); - qr.solve_mut(&mut b); - b - }) + bh.bench_function("qr_solve_10x10", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(10, 10); + (QR::new(m), DVector::::new_random(10)) + }, + |(qr, mut b)| { + qr.solve_mut(&mut b); + (qr, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn qr_solve_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let qr = QR::new(m.clone()); - - bh.bench_function("qr_solve_100x100", move |bh| { - bh.iter(|| { - let mut b = DVector::::from_element(100, 1.0); - qr.solve_mut(&mut b); - b - }) + bh.bench_function("qr_solve_100x100", |bh| { + bh.iter_batched( + || { + let m = DMatrix::::new_random(100, 100); + (QR::new(m), DVector::::new_random(100)) + }, + |(qr, mut b)| { + qr.solve_mut(&mut b); + (qr, b) + }, + criterion::BatchSize::SmallInput, + ) }); } fn qr_inverse_10x10(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(10, 10); - let qr = QR::new(m.clone()); - - bh.bench_function("qr_inverse_10x10", move |bh| { - bh.iter(|| std::hint::black_box(qr.try_inverse())) + bh.bench_function("qr_inverse_10x10", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(10, 10); + QR::new(m) + }, + |qr| qr.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } fn qr_inverse_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let qr = QR::new(m.clone()); - - bh.bench_function("qr_inverse_100x100", move |bh| { - bh.iter(|| std::hint::black_box(qr.try_inverse())) + bh.bench_function("qr_inverse_100x100", |bh| { + bh.iter_batched_ref( + || { + let m = DMatrix::::new_random(100, 100); + QR::new(m) + }, + |qr| qr.try_inverse(), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/schur.rs b/benches/linalg/schur.rs index 4acfa5fb2..24c30e4d7 100644 --- a/benches/linalg/schur.rs +++ b/benches/linalg/schur.rs @@ -1,58 +1,82 @@ -use na::{Matrix4, Schur}; +use na::{DMatrix, SMatrix, Schur}; fn schur_decompose_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("schur_decompose_4x4", move |bh| { - bh.iter(|| std::hint::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_4x4", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| Schur::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn schur_decompose_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("schur_decompose_10x10", move |bh| { - bh.iter(|| std::hint::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| Schur::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn schur_decompose_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("schur_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| Schur::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn schur_decompose_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("schur_decompose_200x200", move |bh| { - bh.iter(|| std::hint::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| Schur::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn eigenvalues_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("eigenvalues_4x4", move |bh| { - bh.iter(|| std::hint::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_4x4", |bh| { + bh.iter_batched_ref( + || SMatrix::::new_random(), + |m| m.complex_eigenvalues(), + criterion::BatchSize::SmallInput, + ) }); } fn eigenvalues_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("eigenvalues_10x10", move |bh| { - bh.iter(|| std::hint::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_10x10", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(10, 10), + |m| m.complex_eigenvalues(), + criterion::BatchSize::SmallInput, + ) }); } fn eigenvalues_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("eigenvalues_100x100", move |bh| { - bh.iter(|| std::hint::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_100x100", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(100, 100), + |m| m.complex_eigenvalues(), + criterion::BatchSize::SmallInput, + ) }); } fn eigenvalues_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("eigenvalues_200x200", move |bh| { - bh.iter(|| std::hint::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_200x200", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(200, 200), + |m| m.complex_eigenvalues(), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/solve.rs b/benches/linalg/solve.rs index 82545cd1a..0c01f5284 100644 --- a/benches/linalg/solve.rs +++ b/benches/linalg/solve.rs @@ -1,90 +1,122 @@ use na::{DMatrix, DVector}; fn solve_l_triangular_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let v = DVector::::new_random(100); - - bh.bench_function("solve_l_triangular_100x100", move |bh| { - bh.iter(|| { - let _ = m.solve_lower_triangular(&v); - }) + bh.bench_function("solve_l_triangular_100x100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DVector::::new_random(100), + ) + }, + |(m, v)| m.solve_lower_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn solve_l_triangular_1000x1000(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(1000, 1000); - let v = DVector::::new_random(1000); - - bh.bench_function("solve_l_triangular_1000x1000", move |bh| { - bh.iter(|| { - let _ = m.solve_lower_triangular(&v); - }) + bh.bench_function("solve_l_triangular_1000x1000", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(1000, 1000), + DVector::::new_random(1000), + ) + }, + |(m, v)| m.solve_lower_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn tr_solve_l_triangular_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let v = DVector::::new_random(100); - - bh.bench_function("tr_solve_l_triangular_100x100", move |bh| { - bh.iter(|| { - let _ = m.tr_solve_lower_triangular(&v); - }) + bh.bench_function("tr_solve_l_triangular_100x100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DVector::::new_random(100), + ) + }, + |(m, v)| m.tr_solve_lower_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn tr_solve_l_triangular_1000x1000(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(1000, 1000); - let v = DVector::::new_random(1000); - - bh.bench_function("tr_solve_l_triangular_1000x1000", move |bh| { - bh.iter(|| { - let _ = m.tr_solve_lower_triangular(&v); - }) + bh.bench_function("tr_solve_l_triangular_1000x1000", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(1000, 1000), + DVector::::new_random(1000), + ) + }, + |(m, v)| m.tr_solve_lower_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn solve_u_triangular_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let v = DVector::::new_random(100); - - bh.bench_function("solve_u_triangular_100x100", move |bh| { - bh.iter(|| { - let _ = m.solve_upper_triangular(&v); - }) + bh.bench_function("solve_u_triangular_100x100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DVector::::new_random(100), + ) + }, + |(m, v)| m.solve_upper_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn solve_u_triangular_1000x1000(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(1000, 1000); - let v = DVector::::new_random(1000); - - bh.bench_function("solve_u_triangular_1000x1000", move |bh| { - bh.iter(|| { - let _ = m.solve_upper_triangular(&v); - }) + bh.bench_function("solve_u_triangular_1000x1000", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(1000, 1000), + DVector::::new_random(1000), + ) + }, + |(m, v)| m.solve_upper_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn tr_solve_u_triangular_100x100(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(100, 100); - let v = DVector::::new_random(100); - - bh.bench_function("tr_solve_u_triangular_100x100", move |bh| { - bh.iter(|| { - let _ = m.tr_solve_upper_triangular(&v); - }) + bh.bench_function("tr_solve_u_triangular_100x100", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(100, 100), + DVector::::new_random(100), + ) + }, + |(m, v)| m.tr_solve_upper_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } fn tr_solve_u_triangular_1000x1000(bh: &mut criterion::Criterion) { - let m = DMatrix::::new_random(1000, 1000); - let v = DVector::::new_random(1000); - - bh.bench_function("tr_solve_u_triangular_1000x1000", move |bh| { - bh.iter(|| { - let _ = m.tr_solve_upper_triangular(&v); - }) + bh.bench_function("tr_solve_u_triangular_1000x1000", |bh| { + bh.iter_batched_ref( + || { + ( + DMatrix::::new_random(1000, 1000), + DVector::::new_random(1000), + ) + }, + |(m, v)| m.tr_solve_upper_triangular(v), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/svd.rs b/benches/linalg/svd.rs index fe279093f..34481ba37 100644 --- a/benches/linalg/svd.rs +++ b/benches/linalg/svd.rs @@ -1,128 +1,182 @@ -use na::{Matrix2, Matrix3, Matrix4, SVD}; +use na::{DMatrix, SMatrix, SVD}; fn svd_decompose_2x2_f32(bh: &mut criterion::Criterion) { - let m = Matrix2::::new_random(); - bh.bench_function("svd_decompose_2x2", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new_unordered(m.clone(), true, true))) + bh.bench_function("svd_decompose_2x2", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn svd_decompose_3x3_f32(bh: &mut criterion::Criterion) { - let m = Matrix3::::new_random(); - bh.bench_function("svd_decompose_3x3", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new_unordered(m.clone(), true, true))) + bh.bench_function("svd_decompose_3x3", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn svd_decompose_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("svd_decompose_4x4", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_4x4", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn svd_decompose_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("svd_decompose_10x10", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn svd_decompose_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("svd_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn svd_decompose_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("svd_decompose_200x200", move |bh| { - bh.iter(|| std::hint::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| SVD::new_unordered(m, true, true), + criterion::BatchSize::SmallInput, + ) }); } fn rank_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("rank_4x4", move |bh| { - bh.iter(|| std::hint::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_4x4", |bh| { + bh.iter_batched_ref( + || SMatrix::::new_random(), + |m| m.rank(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn rank_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("rank_10x10", move |bh| { - bh.iter(|| std::hint::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_10x10", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(10, 10), + |m| m.rank(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn rank_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("rank_100x100", move |bh| { - bh.iter(|| std::hint::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_100x100", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(100, 100), + |m| m.rank(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn rank_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("rank_200x200", move |bh| { - bh.iter(|| std::hint::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_200x200", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(200, 200), + |m| m.rank(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn singular_values_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("singular_values_4x4", move |bh| { - bh.iter(|| std::hint::black_box(m.singular_values())) + bh.bench_function("singular_values_4x4", |bh| { + bh.iter_batched_ref( + || SMatrix::::new_random(), + |m| m.singular_values(), + criterion::BatchSize::SmallInput, + ) }); } fn singular_values_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("singular_values_10x10", move |bh| { - bh.iter(|| std::hint::black_box(m.singular_values())) + bh.bench_function("singular_values_10x10", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(10, 10), + |m| m.singular_values(), + criterion::BatchSize::SmallInput, + ) }); } fn singular_values_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("singular_values_100x100", move |bh| { - bh.iter(|| std::hint::black_box(m.singular_values())) + bh.bench_function("singular_values_100x100", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(100, 100), + |m| m.singular_values(), + criterion::BatchSize::SmallInput, + ) }); } fn singular_values_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("singular_values_200x200", move |bh| { - bh.iter(|| std::hint::black_box(m.singular_values())) + bh.bench_function("singular_values_200x200", |bh| { + bh.iter_batched_ref( + || DMatrix::::new_random(200, 200), + |m| m.singular_values(), + criterion::BatchSize::SmallInput, + ) }); } fn pseudo_inverse_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("pseudo_inverse_4x4", move |bh| { - bh.iter(|| std::hint::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_4x4", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| m.pseudo_inverse(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn pseudo_inverse_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("pseudo_inverse_10x10", move |bh| { - bh.iter(|| std::hint::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| m.pseudo_inverse(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn pseudo_inverse_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("pseudo_inverse_100x100", move |bh| { - bh.iter(|| std::hint::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| m.pseudo_inverse(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } fn pseudo_inverse_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("pseudo_inverse_200x200", move |bh| { - bh.iter(|| std::hint::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| m.pseudo_inverse(1.0e-10), + criterion::BatchSize::SmallInput, + ) }); } diff --git a/benches/linalg/symmetric_eigen.rs b/benches/linalg/symmetric_eigen.rs index 10fa2adf8..d26f56478 100644 --- a/benches/linalg/symmetric_eigen.rs +++ b/benches/linalg/symmetric_eigen.rs @@ -1,30 +1,42 @@ -use na::{Matrix4, SymmetricEigen}; +use na::{DMatrix, SMatrix, SymmetricEigen}; fn symmetric_eigen_decompose_4x4(bh: &mut criterion::Criterion) { - let m = Matrix4::::new_random(); - bh.bench_function("symmetric_eigen_decompose_4x4", move |bh| { - bh.iter(|| std::hint::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_4x4", |bh| { + bh.iter_batched( + || SMatrix::::new_random(), + |m| SymmetricEigen::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn symmetric_eigen_decompose_10x10(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(10, 10); - bh.bench_function("symmetric_eigen_decompose_10x10", move |bh| { - bh.iter(|| std::hint::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_10x10", |bh| { + bh.iter_batched( + || DMatrix::::new_random(10, 10), + |m| SymmetricEigen::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn symmetric_eigen_decompose_100x100(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(100, 100); - bh.bench_function("symmetric_eigen_decompose_100x100", move |bh| { - bh.iter(|| std::hint::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_100x100", |bh| { + bh.iter_batched( + || DMatrix::::new_random(100, 100), + |m| SymmetricEigen::new(m), + criterion::BatchSize::SmallInput, + ) }); } fn symmetric_eigen_decompose_200x200(bh: &mut criterion::Criterion) { - let m = crate::reproducible_dmatrix(200, 200); - bh.bench_function("symmetric_eigen_decompose_200x200", move |bh| { - bh.iter(|| std::hint::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_200x200", |bh| { + bh.iter_batched( + || DMatrix::::new_random(200, 200), + |m| SymmetricEigen::new(m), + criterion::BatchSize::SmallInput, + ) }); }