diff --git a/Cargo.lock b/Cargo.lock index 3cf5d1f..7771a4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "simd-itertools" -version = "0.1.0" +version = "0.2.3" dependencies = [ "criterion", "itertools 0.13.0", diff --git a/benches/all_equal.rs b/benches/all_equal.rs index 61435f6..fd92edc 100644 --- a/benches/all_equal.rs +++ b/benches/all_equal.rs @@ -1,54 +1,53 @@ #![feature(portable_simd)] #![feature(is_sorted)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use itertools::Itertools; -use simd_itertools::AllEqualSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::Simd; -use std::simd::SimdElement; -use std::time::Duration; - -fn benchmark_all_equal<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use simd_itertools::{AllEqualSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; + +fn benchmark_all_equal<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq, Simd: SimdPartialEq>, { - let v1 = vec![T::default(); len]; - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - - group.bench_function(&format!("SIMD all_equal {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().all_equal_simd())) - }); - group.bench_function(&format!("Scalar all_equal {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().all_equal())) - }); + let mut group = c.benchmark_group(format!("all-equal-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().all_equal_simd())) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().all_equal())) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_all_equal::(c, "u8", n); - benchmark_all_equal::(c, "i8", n); - benchmark_all_equal::(c, "u16", n); - benchmark_all_equal::(c, "i16", n); - benchmark_all_equal::(c, "u32", n); - benchmark_all_equal::(c, "i32", n); - benchmark_all_equal::(c, "u64", n); - benchmark_all_equal::(c, "i64", n); - benchmark_all_equal::(c, "f32", n); - benchmark_all_equal::(c, "f64", n); - benchmark_all_equal::(c, "isize", n); - benchmark_all_equal::(c, "usize", n); - } + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); + benchmark_all_equal::(c); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/contains.rs b/benches/contains.rs index 6878d98..9161511 100644 --- a/benches/contains.rs +++ b/benches/contains.rs @@ -2,77 +2,84 @@ #![feature(is_sorted)] #![feature(sort_floats)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use itertools::Itertools; -use simd_itertools::ContainsSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; +use simd_itertools::{ContainsSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let needle: T = 55.try_into().unwrap(); + let mut group = c.benchmark_group(format!("contains-{}", std::any::type_name::())); + let mut len = 1; - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = 55.try_into().unwrap(); - group.bench_function(&format!("SIMD contains {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().contains_simd(&needle))) - }); - group.bench_function(&format!("Scalar contains {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().contains(&needle))) - }); + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().contains_simd(&needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().contains(&needle))) + }); + + len *= 10; + } + + group.finish(); } -fn benchmark_contains_floats<'a, T: 'static + Copy + PartialEq + Default + Debug>( - c: &mut Criterion, - name: &str, - len: usize, -) where +fn benchmark_contains_floats<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug + std::convert::From, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let v2 = vec![T::default(); len]; - let needle: T = 55.0.try_into().unwrap(); - assert_eq!(v1, v2); + let mut group = c.benchmark_group(format!("contains-float-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let v2 = vec![T::default(); len]; + let needle: T = 55.0.try_into().unwrap(); + assert_eq!(v1, v2); - c.bench_function(&format!("SIMD contains {}", name), |b| { - b.iter(|| black_box(v1.iter().contains_simd(&needle))) - }); - c.bench_function(&format!("trivial contains {}", name), |b| { - b.iter(|| black_box(v1.iter().contains(&needle))) - }); + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().contains_simd(&needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().contains(&needle))) + }); + + len *= 10; + } + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - benchmark_contains_floats::(c, "f32", n); - benchmark_contains_floats::(c, "f64", n); - } + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains::(c); + benchmark_contains_floats::(c); + benchmark_contains_floats::(c); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/eq.rs b/benches/eq.rs index 0c61cf5..10c47e9 100644 --- a/benches/eq.rs +++ b/benches/eq.rs @@ -1,52 +1,53 @@ #![feature(portable_simd)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::EqSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; - -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{EqSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; + +fn benchmark_eq<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq, Simd: SimdPartialEq>, { - let v1 = black_box(vec![T::default(); len]); - let v2 = black_box(vec![T::default(); len]); - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - - group.bench_function(&format!("SIMD eq {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().eq_simd(&v2.iter()))) - }); - group.bench_function(&format!("Scalar eq {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().eq(&v2))) - }); + let mut group = c.benchmark_group(format!("eq-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = black_box(vec![T::default(); len]); + let v2 = black_box(vec![T::default(); len]); + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().eq_simd(&v2.iter()))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().eq(&v2))) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - benchmark_contains::(c, "f32", n); - benchmark_contains::(c, "f64", n); - } + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); + benchmark_eq::(c); } + criterion_group!(benches, criterion_benchmark); criterion_main!(benches); diff --git a/benches/filter.rs b/benches/filter.rs index 2325629..f19144e 100644 --- a/benches/filter.rs +++ b/benches/filter.rs @@ -1,54 +1,54 @@ #![feature(portable_simd)] -#![feature(is_sorted)] -#![feature(sort_floats)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use simd_itertools::FilterSimd; -use std::fmt::Debug; -use std::simd::cmp::SimdPartialOrd; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; - -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use std::{ + fmt::Debug, + simd::{cmp::SimdPartialOrd, Mask, Simd, SimdElement}, +}; + +fn benchmark_filter<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug + PartialOrd, Simd: SimdPartialOrd>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let needle: T = 55.try_into().unwrap(); - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD filter {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().filter_simd_lt(needle))) - }); - group.bench_function(&format!("Scalar filter {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().filter(|x| **x < needle))) - }); + let mut group = c.benchmark_group(format!("filter-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = 55.try_into().unwrap(); + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().filter_simd_lt(needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().filter(|x| **x < needle))) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - } + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); + benchmark_filter::(c); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/find.rs b/benches/find.rs index 322f248..746f6b4 100644 --- a/benches/find.rs +++ b/benches/find.rs @@ -2,78 +2,82 @@ #![feature(is_sorted)] #![feature(sort_floats)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::FindSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{FindSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +fn benchmark_find<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let needle: T = 55.try_into().unwrap(); + let mut group = c.benchmark_group(format!("find-{}", std::any::type_name::())); + let mut len = 1; - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD find {}@{}", name, len), |b| { - b.iter(|| black_box(v1.iter().find_simd(needle))) - }); - group.bench_function(&format!("Scalar find {}@{}", name, len), |b| { - b.iter(|| black_box(v1.iter().find(|x| **x == needle))) - }); + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = 55.try_into().unwrap(); + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().find_simd(needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().find(|x| **x == needle))) + }); + + len *= 10; + } + + group.finish(); } -fn benchmark_contains_floats<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where + +fn benchmark_find_float<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug + std::convert::From, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let v2 = vec![T::default(); len]; - let needle: T = 55.0.try_into().unwrap(); - assert_eq!(v1, v2); + let mut group = c.benchmark_group(format!("find-float-{}", std::any::type_name::())); + let mut len = 1; - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = (55.0).try_into().unwrap(); - group.bench_function(&format!("SIMD find {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().find_simd(needle))) - }); - group.bench_function(&format!("Scalar find {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().find(|x| **x == needle))) - }); + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().find_simd(needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().find(|x| **x == needle))) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - benchmark_contains_floats::(c, "f32", n); - benchmark_contains_floats::(c, "f64", n); - } + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find::(c); + benchmark_find_float::(c); + benchmark_find_float::(c); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/is_sorted.rs b/benches/is_sorted.rs index 96e2ca1..7efd330 100644 --- a/benches/is_sorted.rs +++ b/benches/is_sorted.rs @@ -1,53 +1,52 @@ #![feature(portable_simd)] #![feature(is_sorted)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::IsSortedSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialOrd; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; - -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{IsSortedSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialOrd, Mask, Simd, SimdElement}, +}; + +fn benchmark_is_sorted<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + Debug + std::cmp::PartialOrd, Simd: SimdPartialOrd>, { - let v1 = vec![T::default(); len]; - let v2 = vec![T::default(); len]; - assert_eq!(v1, v2); - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD is_sorted {} {}", name, len), |b| { - b.iter(|| black_box(black_box(&v1).iter().is_sorted_simd())) - }); - group.bench_function(&format!("Scalar is_sorted {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().is_sorted())) - }); + let mut group = c.benchmark_group(format!("is-sorted-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().is_sorted_simd())) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().is_sorted())) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - benchmark_contains::(c, "f32", n); - benchmark_contains::(c, "f64", n); - } + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); + benchmark_is_sorted::(c); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/max.rs b/benches/max.rs index e921fc4..3d6916a 100644 --- a/benches/max.rs +++ b/benches/max.rs @@ -1,49 +1,50 @@ #![feature(portable_simd)] #![feature(is_sorted)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::MaxSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; - -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{MaxSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; + +fn benchmark_max<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + std::cmp::Ord, Simd: SimdPartialEq>, { - let v1 = black_box(vec![T::default(); len]); - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD max {} {}", name, len), |b| { - b.iter(|| black_box(black_box(&v1).iter().max_simd())) - }); - group.bench_function(&format!("Scalar max {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().max())) - }); + let mut group = c.benchmark_group(format!("max-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().max_simd())) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().max())) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - } + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); + benchmark_max::(c); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches); diff --git a/benches/min.rs b/benches/min.rs index 7dcbfd0..6e0cc82 100644 --- a/benches/min.rs +++ b/benches/min.rs @@ -1,48 +1,49 @@ #![feature(portable_simd)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::MinSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; - -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{MinSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; + +fn benchmark_min<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + std::cmp::Ord, Simd: SimdPartialEq>, { - let v1 = black_box(vec![T::default(); len]); - - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD min {} {}", name, len), |b| { - b.iter(|| black_box(black_box(&v1).iter().min_simd())) - }); - group.bench_function(&format!("Scalar min {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().min())) - }); + let mut group = c.benchmark_group(format!("min-{}", std::any::type_name::())); + let mut len = 1; + + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().min_simd())) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().min())) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - } + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); + benchmark_min::(c); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches); diff --git a/benches/position.rs b/benches/position.rs index d5fde9f..1cdd3f9 100644 --- a/benches/position.rs +++ b/benches/position.rs @@ -2,78 +2,84 @@ #![feature(is_sorted)] #![feature(sort_floats)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use simd_itertools::PositionSimd; -use simd_itertools::SIMD_LEN; -use std::fmt::Debug; -use std::simd::prelude::SimdPartialEq; -use std::simd::Mask; -use std::simd::{Simd, SimdElement}; -use std::time::Duration; +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use simd_itertools::{PositionSimd, SIMD_LEN}; +use std::{ + fmt::Debug, + simd::{prelude::SimdPartialEq, Mask, Simd, SimdElement}, +}; -fn benchmark_contains<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where +fn benchmark_position<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let needle: T = 55.try_into().unwrap(); + let mut group = c.benchmark_group(format!("position-{}", std::any::type_name::())); + let mut len = 1; - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); - group.bench_function(&format!("SIMD position {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().position_simd(needle))) - }); - group.bench_function(&format!("Scalar position {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().position(|x| *x == needle))) - }); + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = 55.try_into().unwrap(); + + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().position_simd(needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().position(|x| *x == needle))) + }); + + len *= 10; + } + + group.finish(); } -fn benchmark_contains_floats<'a, T: 'static + Copy + PartialEq + Default + Debug>( - _c: &mut Criterion, - name: &str, - len: usize, -) where + +fn benchmark_position_floats<'a, T: 'static + Copy + PartialEq + Default + Debug>(c: &mut Criterion) +where T: SimdElement + std::cmp::PartialEq + TryFrom + Debug + std::convert::From, Simd: SimdPartialEq>, >::Error: Debug, { - let v1 = vec![T::default(); len]; - let needle: T = 55.0.try_into().unwrap(); + let mut group = c.benchmark_group(format!("position-floats-{}", std::any::type_name::())); + let mut len = 1; - let mut group = Criterion::default() - .warm_up_time(Duration::from_secs(1)) - .measurement_time(Duration::from_secs(1)); + while len < (1 << 11) { + let v1 = vec![T::default(); len]; + let needle: T = (55.0).try_into().unwrap(); - group.bench_function(&format!("SIMD position {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().position_simd(needle))) - }); - group.bench_function(&format!("Scalar position {} {}", name, len), |b| { - b.iter(|| black_box(v1.iter().position(|x| *x == needle))) - }); + group.throughput(Throughput::Elements(len as u64)); + + group.bench_function(BenchmarkId::new("SIMD", len), |b| { + b.iter(|| black_box(v1.iter().position_simd(needle))) + }); + group.bench_function(BenchmarkId::new("Scalar", len), |b| { + b.iter(|| black_box(v1.iter().position(|x| *x == needle))) + }); + + len *= 10; + } + + group.finish(); } fn criterion_benchmark(c: &mut Criterion) { - for n in (0..200).map(|x| x * 10) { - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "u32", n); - benchmark_contains::(c, "u8", n); - benchmark_contains::(c, "i8", n); - benchmark_contains::(c, "u16", n); - benchmark_contains::(c, "i16", n); - benchmark_contains::(c, "i32", n); - benchmark_contains::(c, "u64", n); - benchmark_contains::(c, "i64", n); - benchmark_contains::(c, "isize", n); - benchmark_contains::(c, "usize", n); - benchmark_contains_floats::(c, "f32", n); - benchmark_contains_floats::(c, "f64", n); - } + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position::(c); + benchmark_position_floats::(c); + benchmark_position_floats::(c); } criterion_group!(benches, criterion_benchmark);