use criterion::{black_box, criterion_group, criterion_main, Criterion}; use itertools::Itertools; use itertools::free::cloned; use itertools::iproduct;
use std::iter::repeat; use std::cmp; use std::ops::{Add, Range};
mod extra;
usecrate::extra::ZipSlices;
fn slice_iter(c: &mut Criterion) { let xs: Vec<_> = repeat(1i32).take(20).collect();
c.bench_function("slice iter", move |b| {
b.iter(|| for elt in xs.iter() {
black_box(elt);
})
});
}
fn slice_iter_rev(c: &mut Criterion) { let xs: Vec<_> = repeat(1i32).take(20).collect();
c.bench_function("slice iter rev", move |b| {
b.iter(|| for elt in xs.iter().rev() {
black_box(elt);
})
});
}
fn zip_default_zip(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zip default zip", move |b| {
b.iter(|| { for (&x, &y) in xs.iter().zip(&ys) {
black_box(x);
black_box(y);
}
})
});
}
fn zipdot_i32_default_zip(c: &mut Criterion) { let xs = vec![2; 1024]; let ys = vec![2; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot i32 default zip", move |b| {
b.iter(|| { letmut s = 0; for (&x, &y) in xs.iter().zip(&ys) {
s += x * y;
}
s
})
});
}
fn zipdot_f32_default_zip(c: &mut Criterion) { let xs = vec![2f32; 1024]; let ys = vec![2f32; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot f32 default zip", move |b| {
b.iter(|| { letmut s = 0.; for (&x, &y) in xs.iter().zip(&ys) {
s += x * y;
}
s
})
});
}
fn zip_default_zip3(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; let zs = vec![0; 766]; let xs = black_box(xs); let ys = black_box(ys); let zs = black_box(zs);
fn zipdot_i32_zipslices(c: &mut Criterion) { let xs = vec![2; 1024]; let ys = vec![2; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot i32 zipslices", move |b| {
b.iter(|| { letmut s = 0i32; for (&x, &y) in ZipSlices::new(&xs, &ys) {
s += x * y;
}
s
})
});
}
fn zipdot_f32_zipslices(c: &mut Criterion) { let xs = vec![2f32; 1024]; let ys = vec![2f32; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot f32 zipslices", move |b| {
b.iter(|| { letmut s = 0.; for (&x, &y) in ZipSlices::new(&xs, &ys) {
s += x * y;
}
s
})
});
}
fn zip_checked_counted_loop(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zip checked counted loop", move |b| {
b.iter(|| { // Must slice to equal lengths, and then bounds checks are eliminated! let len = cmp::min(xs.len(), ys.len()); let xs = &xs[..len]; let ys = &ys[..len];
for i in0..len { let x = xs[i]; let y = ys[i];
black_box(x);
black_box(y);
}
})
});
}
fn zipdot_i32_checked_counted_loop(c: &mut Criterion) { let xs = vec![2; 1024]; let ys = vec![2; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot i32 checked counted loop", move |b| {
b.iter(|| { // Must slice to equal lengths, and then bounds checks are eliminated! let len = cmp::min(xs.len(), ys.len()); let xs = &xs[..len]; let ys = &ys[..len];
letmut s = 0i32;
for i in0..len {
s += xs[i] * ys[i];
}
s
})
});
}
fn zipdot_f32_checked_counted_loop(c: &mut Criterion) { let xs = vec![2f32; 1024]; let ys = vec![2f32; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot f32 checked counted loop", move |b| {
b.iter(|| { // Must slice to equal lengths, and then bounds checks are eliminated! let len = cmp::min(xs.len(), ys.len()); let xs = &xs[..len]; let ys = &ys[..len];
letmut s = 0.;
for i in0..len {
s += xs[i] * ys[i];
}
s
})
});
}
fn zipdot_f32_checked_counted_unrolled_loop(c: &mut Criterion) { let xs = vec![2f32; 1024]; let ys = vec![2f32; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot f32 checked counted unrolled loop", move |b| {
b.iter(|| { // Must slice to equal lengths, and then bounds checks are eliminated! let len = cmp::min(xs.len(), ys.len()); letmut xs = &xs[..len]; letmut ys = &ys[..len];
// how to unroll and have bounds checks eliminated (by cristicbz) // split sum into eight parts to enable vectorization (by bluss) while xs.len() >= 8 {
p0 += xs[0] * ys[0];
p1 += xs[1] * ys[1];
p2 += xs[2] * ys[2];
p3 += xs[3] * ys[3];
p4 += xs[4] * ys[4];
p5 += xs[5] * ys[5];
p6 += xs[6] * ys[6];
p7 += xs[7] * ys[7];
xs = &xs[8..];
ys = &ys[8..];
}
s += p0 + p4;
s += p1 + p5;
s += p2 + p6;
s += p3 + p7;
for i in0..xs.len() {
s += xs[i] * ys[i];
}
s
})
});
}
fn zip_unchecked_counted_loop(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zip unchecked counted loop", move |b| {
b.iter(|| { let len = cmp::min(xs.len(), ys.len()); for i in0..len { unsafe { let x = *xs.get_unchecked(i); let y = *ys.get_unchecked(i);
black_box(x);
black_box(y);
}
}
})
});
}
fn zipdot_i32_unchecked_counted_loop(c: &mut Criterion) { let xs = vec![2; 1024]; let ys = vec![2; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot i32 unchecked counted loop", move |b| {
b.iter(|| { let len = cmp::min(xs.len(), ys.len()); letmut s = 0i32; for i in0..len { unsafe { let x = *xs.get_unchecked(i); let y = *ys.get_unchecked(i);
s += x * y;
}
}
s
})
});
}
fn zipdot_f32_unchecked_counted_loop(c: &mut Criterion) { let xs = vec![2.; 1024]; let ys = vec![2.; 768]; let xs = black_box(xs); let ys = black_box(ys);
c.bench_function("zipdot f32 unchecked counted loop", move |b| {
b.iter(|| { let len = cmp::min(xs.len(), ys.len()); letmut s = 0f32; for i in0..len { unsafe { let x = *xs.get_unchecked(i); let y = *ys.get_unchecked(i);
s += x * y;
}
}
s
})
});
}
fn zip_unchecked_counted_loop3(c: &mut Criterion) { let xs = vec![0; 1024]; let ys = vec![0; 768]; let zs = vec![0; 766]; let xs = black_box(xs); let ys = black_box(ys); let zs = black_box(zs);
c.bench_function("zip unchecked counted loop3", move |b| {
b.iter(|| { let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); for i in0..len { unsafe { let x = *xs.get_unchecked(i); let y = *ys.get_unchecked(i); let z = *zs.get_unchecked(i);
black_box(x);
black_box(y);
black_box(z);
}
}
})
});
}
fn group_by_lazy_1(c: &mut Criterion) { letmut data = vec![0; 1024]; for (index, elt) in data.iter_mut().enumerate() {
*elt = index / 10;
}
let data = black_box(data);
c.bench_function("group by lazy 1", move |b| {
b.iter(|| { for (_key, group) in &data.iter().group_by(|elt| **elt) { for elt in group {
black_box(elt);
}
}
})
});
}
fn group_by_lazy_2(c: &mut Criterion) { letmut data = vec![0; 1024]; for (index, elt) in data.iter_mut().enumerate() {
*elt = index / 2;
}
let data = black_box(data);
c.bench_function("group by lazy 2", move |b| {
b.iter(|| { for (_key, group) in &data.iter().group_by(|elt| **elt) { for elt in group {
black_box(elt);
}
}
})
});
}
fn slice_chunks(c: &mut Criterion) { let data = vec![0; 1024];
let data = black_box(data); let sz = black_box(10);
c.bench_function("slice chunks", move |b| {
b.iter(|| { for group in data.chunks(sz) { for elt in group {
black_box(elt);
}
}
})
});
}
fn chunks_lazy_1(c: &mut Criterion) { let data = vec![0; 1024];
let data = black_box(data); let sz = black_box(10);
c.bench_function("chunks lazy 1", move |b| {
b.iter(|| { for group in &data.iter().chunks(sz) { for elt in group {
black_box(elt);
}
}
})
});
}
fn equal(c: &mut Criterion) { let data = vec![7; 1024]; let l = data.len(); let alpha = black_box(&data[1..]); let beta = black_box(&data[..l - 1]);
fn merge_default(c: &mut Criterion) { letmut data1 = vec![0; 1024]; letmut data2 = vec![0; 800]; letmut x = 0; for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
letmut y = 0; for (i, elt) in data2.iter_mut().enumerate() {
*elt += y; if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
} let data1 = black_box(data1); let data2 = black_box(data2);
fn merge_by_cmp(c: &mut Criterion) { letmut data1 = vec![0; 1024]; letmut data2 = vec![0; 800]; letmut x = 0; for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
letmut y = 0; for (i, elt) in data2.iter_mut().enumerate() {
*elt += y; if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
} let data1 = black_box(data1); let data2 = black_box(data2);
fn merge_by_lt(c: &mut Criterion) { letmut data1 = vec![0; 1024]; letmut data2 = vec![0; 800]; letmut x = 0; for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
letmut y = 0; for (i, elt) in data2.iter_mut().enumerate() {
*elt += y; if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
} let data1 = black_box(data1); let data2 = black_box(data2);
c.bench_function("merge by lt", move |b| {
b.iter(|| {
data1.iter().merge_by(&data2, |a, b| a <= b).count()
})
});
}
fn kmerge_default(c: &mut Criterion) { letmut data1 = vec![0; 1024]; letmut data2 = vec![0; 800]; letmut x = 0; for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
letmut y = 0; for (i, elt) in data2.iter_mut().enumerate() {
*elt += y; if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
} let data1 = black_box(data1); let data2 = black_box(data2); let its = &[data1.iter(), data2.iter()];
fn cartesian_product_iterator(c: &mut Criterion) { let xs = vec![0; 16];
c.bench_function("cartesian product iterator", move |b| {
b.iter(|| { letmut sum = 0; for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) {
sum += x;
sum += y;
sum += z;
}
sum
})
});
}
fn cartesian_product_fold(c: &mut Criterion) { let xs = vec![0; 16];
c.bench_function("cartesian product fold", move |b| {
b.iter(|| { letmut sum = 0;
iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| {
sum += x;
sum += y;
sum += z;
});
sum
})
});
}
c.bench_function("multi cartesian product iterator", move |b| {
b.iter(|| { letmut sum = 0; for x in xs.iter().multi_cartesian_product() {
sum += x[0];
sum += x[1];
sum += x[2];
}
sum
})
});
}
c.bench_function("multi cartesian product fold", move |b| {
b.iter(|| { letmut sum = 0;
xs.iter().multi_cartesian_product().fold((), |(), x| {
sum += x[0];
sum += x[1];
sum += x[2];
});
sum
})
});
}
fn cartesian_product_nested_for(c: &mut Criterion) { let xs = vec![0; 16];
c.bench_function("cartesian product nested for", move |b| {
b.iter(|| { letmut sum = 0; for &x in &xs { for &y in &xs { for &z in &xs {
sum += x;
sum += y;
sum += z;
}
}
}
sum
})
});
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.