#![feature(test)] #![allow( clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::many_single_char_names )] extern crate test; use rawpointer::PointerExt; use test::black_box; use test::Bencher; use ndarray::prelude::*; use ndarray::Slice; use ndarray::{FoldWhile, Zip}; #[bench] fn iter_sum_2d_regular(bench: &mut Bencher) { let a = Array::::zeros((64, 64)); bench.iter(|| a.iter().sum::()); } #[bench] fn iter_sum_2d_cutout(bench: &mut Bencher) { let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = av; bench.iter(|| a.iter().sum::()); } #[bench] fn iter_all_2d_cutout(bench: &mut Bencher) { let a = Array::::zeros((66, 66)); let av = a.slice(s![1..-1, 1..-1]); let a = av; bench.iter(|| a.iter().all(|&x| x >= 0)); } #[bench] fn iter_sum_2d_transpose(bench: &mut Bencher) { let a = Array::::zeros((66, 66)); let a = a.t(); bench.iter(|| a.iter().sum::()); } #[bench] fn iter_filter_sum_2d_u32(bench: &mut Bencher) { let a = Array::linspace(0., 1., 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); bench.iter(|| b.iter().filter(|&&x| x < 75).sum::()); } #[bench] fn iter_filter_sum_2d_f32(bench: &mut Bencher) { let a = Array::linspace(0., 1., 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; bench.iter(|| b.iter().filter(|&&x| x < 75.).sum::()); } #[bench] fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher) { let a = Array::linspace(0., 1., 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a.mapv(|x| (x * 100.) as u32); let b = b.slice(s![.., ..;2]); bench.iter(|| b.iter().filter(|&&x| x < 75).sum::()); } #[bench] fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher) { let a = Array::linspace(0., 1., 256) .into_shape_with_order((16, 16)) .unwrap(); let b = a * 100.; let b = b.slice(s![.., ..;2]); bench.iter(|| b.iter().filter(|&&x| x < 75.).sum::()); } #[bench] fn iter_rev_step_by_contiguous(bench: &mut Bencher) { let a = Array::linspace(0., 1., 512); bench.iter(|| { a.iter().rev().step_by(2).for_each(|x| { black_box(x); }) }); } #[bench] fn iter_rev_step_by_discontiguous(bench: &mut Bencher) { let mut a = Array::linspace(0., 1., 1024); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); bench.iter(|| { a.iter().rev().step_by(2).for_each(|x| { black_box(x); }) }); } const ZIPSZ: usize = 10_000; #[bench] fn sum_3_std_zip1(bench: &mut Bencher) { let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; let c = vec![1; ZIPSZ]; bench.iter(|| { a.iter() .zip(b.iter().zip(&c)) .fold(0, |acc, (&a, (&b, &c))| acc + a + b + c) }); } #[bench] fn sum_3_std_zip2(bench: &mut Bencher) { let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; let c = vec![1; ZIPSZ]; bench.iter(|| { a.iter() .zip(b.iter()) .zip(&c) .fold(0, |acc, ((&a, &b), &c)| acc + a + b + c) }); } #[bench] fn sum_3_std_zip3(bench: &mut Bencher) { let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; let c = vec![1; ZIPSZ]; bench.iter(|| { let mut s = 0; for ((&a, &b), &c) in a.iter().zip(b.iter()).zip(&c) { s += a + b + c } s }); } #[bench] fn vector_sum_3_std_zip(bench: &mut Bencher) { let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; let mut c = vec![1.; ZIPSZ]; bench.iter(|| { for ((&a, &b), c) in a.iter().zip(b.iter()).zip(&mut c) { *c += a + b; } }); } #[bench] fn sum_3_azip(bench: &mut Bencher) { let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; let c = vec![1; ZIPSZ]; bench.iter(|| { let mut s = 0; azip!((&a in &a, &b in &b, &c in &c) { s += a + b + c; }); s }); } #[bench] fn sum_3_azip_fold(bench: &mut Bencher) { let a = vec![1; ZIPSZ]; let b = vec![1; ZIPSZ]; let c = vec![1; ZIPSZ]; bench.iter(|| { Zip::from(&a) .and(&b) .and(&c) .fold_while(0, |acc, &a, &b, &c| FoldWhile::Continue(acc + a + b + c)) .into_inner() }); } #[bench] fn vector_sum_3_azip(bench: &mut Bencher) { let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; let mut c = vec![1.; ZIPSZ]; bench.iter(|| { azip!((&a in &a, &b in &b, c in &mut c) { *c += a + b; }); }); } fn vector_sum3_unchecked(a: &[f64], b: &[f64], c: &mut [f64]) { for i in 0..c.len() { unsafe { *c.get_unchecked_mut(i) += *a.get_unchecked(i) + *b.get_unchecked(i); } } } #[bench] fn vector_sum_3_zip_unchecked(bench: &mut Bencher) { let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; let mut c = vec![1.; ZIPSZ]; bench.iter(move || { vector_sum3_unchecked(&a, &b, &mut c); }); } #[bench] fn vector_sum_3_zip_unchecked_manual(bench: &mut Bencher) { let a = vec![1.; ZIPSZ]; let b = vec![1.; ZIPSZ]; let mut c = vec![1.; ZIPSZ]; bench.iter(move || unsafe { let mut ap = a.as_ptr(); let mut bp = b.as_ptr(); let mut cp = c.as_mut_ptr(); let cend = cp.add(c.len()); while cp != cend { *cp.post_inc() += *ap.post_inc() + *bp.post_inc(); } }); } // index iterator size const ISZ: usize = 16; const I2DSZ: usize = 64; #[bench] fn indexed_iter_1d_ix1(bench: &mut Bencher) { let mut a = Array::::zeros(I2DSZ * I2DSZ); for (i, elt) in a.indexed_iter_mut() { *elt = i as _; } bench.iter(|| { for (i, &_elt) in a.indexed_iter() { //assert!(a[i] == elt); black_box(i); } }) } #[bench] fn indexed_zip_1d_ix1(bench: &mut Bencher) { let mut a = Array::::zeros(I2DSZ * I2DSZ); for (i, elt) in a.indexed_iter_mut() { *elt = i as _; } bench.iter(|| { Zip::indexed(&a).for_each(|i, &_elt| { black_box(i); //assert!(a[i] == elt); }); }) } #[bench] fn indexed_iter_2d_ix2(bench: &mut Bencher) { let mut a = Array::::zeros((I2DSZ, I2DSZ)); for ((i, j), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j) as _; } bench.iter(|| { for (i, &_elt) in a.indexed_iter() { //assert!(a[i] == elt); black_box(i); } }) } #[bench] fn indexed_zip_2d_ix2(bench: &mut Bencher) { let mut a = Array::::zeros((I2DSZ, I2DSZ)); for ((i, j), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j) as _; } bench.iter(|| { Zip::indexed(&a).for_each(|i, &_elt| { black_box(i); //assert!(a[i] == elt); }); }) } #[bench] fn indexed_iter_3d_ix3(bench: &mut Bencher) { let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } bench.iter(|| { for (i, &_elt) in a.indexed_iter() { //assert!(a[i] == elt); black_box(i); } }) } #[bench] fn indexed_zip_3d_ix3(bench: &mut Bencher) { let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } bench.iter(|| { Zip::indexed(&a).for_each(|i, &_elt| { black_box(i); //assert!(a[i] == elt); }); }) } #[bench] fn indexed_iter_3d_dyn(bench: &mut Bencher) { let mut a = Array::::zeros((ISZ, ISZ, ISZ)); for ((i, j, k), elt) in a.indexed_iter_mut() { *elt = (i + 100 * j + 10000 * k) as _; } let a = a.into_shape_with_order(&[ISZ; 3][..]).unwrap(); bench.iter(|| { for (i, &_elt) in a.indexed_iter() { //assert!(a[i] == elt); black_box(i); } }) } #[bench] fn iter_sum_1d_strided_fold(bench: &mut Bencher) { let mut a = Array::::ones(10240); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); bench.iter(|| a.iter().sum::()); } #[bench] fn iter_sum_1d_strided_rfold(bench: &mut Bencher) { let mut a = Array::::ones(10240); a.slice_axis_inplace(Axis(0), Slice::new(0, None, 2)); bench.iter(|| a.iter().rfold(0, |acc, &x| acc + x)); } #[bench] fn iter_axis_iter_sum(bench: &mut Bencher) { let a = Array::::zeros((64, 64)); bench.iter(|| a.axis_iter(Axis(0)).map(|plane| plane.sum()).sum::()); } #[bench] fn iter_axis_chunks_1_iter_sum(bench: &mut Bencher) { let a = Array::::zeros((64, 64)); bench.iter(|| { a.axis_chunks_iter(Axis(0), 1) .map(|plane| plane.sum()) .sum::() }); } #[bench] fn iter_axis_chunks_5_iter_sum(bench: &mut Bencher) { let a = Array::::zeros((64, 64)); bench.iter(|| { a.axis_chunks_iter(Axis(0), 5) .map(|plane| plane.sum()) .sum::() }); } pub fn zip_mut_with(data: &Array3, out: &mut Array3) { out.zip_mut_with(&data, |o, &i| { *o = i; }); } #[bench] fn zip_mut_with_cc(b: &mut Bencher) { let data: Array3 = Array3::zeros((ISZ, ISZ, ISZ)); let mut out = Array3::zeros(data.dim()); b.iter(|| zip_mut_with(&data, &mut out)); } #[bench] fn zip_mut_with_ff(b: &mut Bencher) { let data: Array3 = Array3::zeros((ISZ, ISZ, ISZ).f()); let mut out = Array3::zeros(data.dim().f()); b.iter(|| zip_mut_with(&data, &mut out)); }