use criterion::{criterion_group, criterion_main, Criterion, Fun};
use rand::distributions::{Distribution, Standard};
use rand::prelude::*;
#[cfg(feature = "rayon")]
use rayon::prelude::*;
static SEED: [u8; 32] = [3; 32];
static BUF_SIZE: usize = 750_000;
#[inline]
fn make_random_vec<T>() -> Vec<T>
where
Standard: Distribution<T>,
{
let n = BUF_SIZE;
let mut rng: StdRng = SeedableRng::from_seed(SEED);
let mut vec = Vec::new();
for _ in 0..n {
vec.push(rng.gen::<T>());
}
vec
}
fn benchmark(v: &mut Vec<f64>, v1: &mut Vec<f64>) {
let f = |x, y| x * 3.6321 + 42314.0 * y;
for (a, b) in v.iter_mut().zip(v1.iter_mut()) {
let (mut a2, mut b2) = (*a, *b);
a2 = f(a2, b2);
b2 = f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
*a = a2;
*b = b2;
}
}
fn unnecessary_zipping(
v: &mut Vec<f64>,
v1: &mut Vec<f64>,
v2: &mut Vec<f64>,
v3: &mut Vec<f64>,
v4: &mut Vec<f64>,
v5: &mut Vec<f64>,
v6: &mut Vec<f64>,
) {
let f = |x, y| x * 3.6321 + 42314.0 * y;
for ((((((a, b), _c), _d), _e), _f), _g) in v
.iter_mut()
.zip(v1.iter_mut())
.zip(v2.iter_mut())
.zip(v3.iter_mut())
.zip(v4.iter_mut())
.zip(v5.iter_mut())
.zip(v6.iter_mut())
{
let (mut a2, mut b2) = (*a, *b);
a2 = f(a2, b2);
b2 = f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
*a = a2;
*b = b2;
}
}
fn unnecessary_zipping_with_map(
v: &mut Vec<f64>,
v1: &mut Vec<f64>,
v2: &mut Vec<f64>,
v3: &mut Vec<f64>,
v4: &mut Vec<f64>,
v5: &mut Vec<f64>,
v6: &mut Vec<f64>,
) {
let f = |x, y| x * 3.6321 + 42314.0 * y;
for (a, b, _c, _d, _e, _f, _g) in v
.iter_mut()
.zip(v1.iter_mut())
.zip(v2.iter_mut())
.zip(v3.iter_mut())
.zip(v4.iter_mut())
.zip(v5.iter_mut())
.zip(v6.iter_mut())
.map(|((((((a, b), c), d), e), f), g)| (a, b, c, d, e, f, g))
{
let (mut a2, mut b2) = (*a, *b);
a2 = f(a2, b2);
b2 = f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
b2 += f(b2, a2);
a2 += f(a2, b2);
*a = a2;
*b = b2;
}
}
#[allow(dead_code)]
struct Group {
a: f64,
b: f64,
c: f64,
d: f64,
e: f64,
f: f64,
g: f64,
}
fn unnecessary_zipping_with_struct(
v: &mut Vec<f64>,
v1: &mut Vec<f64>,
v2: &mut Vec<f64>,
v3: &mut Vec<f64>,
v4: &mut Vec<f64>,
v5: &mut Vec<f64>,
v6: &mut Vec<f64>,
) {
let fu = |x, y| x * 3.6321 + 42314.0 * y;
for ((((((a, b), c), d), e), f), g) in v
.iter_mut()
.zip(v1.iter_mut())
.zip(v2.iter_mut())
.zip(v3.iter_mut())
.zip(v4.iter_mut())
.zip(v5.iter_mut())
.zip(v6.iter_mut())
{
let mut group = Group {
a: *a,
b: *b,
c: *c,
d: *d,
e: *e,
f: *f,
g: *g,
};
group.a = fu(group.a, group.b);
group.b = fu(group.b, group.a);
group.a += fu(group.a, group.b);
group.b += fu(group.b, group.a);
group.a += fu(group.a, group.b);
group.b += fu(group.b, group.a);
group.a += fu(group.a, group.b);
*a = group.a;
*b = group.b;
}
}
fn zipping(
v: &mut Vec<f64>,
v1: &mut Vec<f64>,
v2: &mut Vec<f64>,
v3: &mut Vec<f64>,
v4: &mut Vec<f64>,
v5: &mut Vec<f64>,
v6: &mut Vec<f64>,
) {
let f = |x, y| x * 3.6321 + 42314.0 * y;
for ((((((a, b), c), d), e), f2), g) in v
.iter_mut()
.zip(v1.iter_mut())
.zip(v2.iter_mut())
.zip(v3.iter_mut())
.zip(v4.iter_mut())
.zip(v5.iter_mut())
.zip(v6.iter_mut())
{
let (mut a2, mut b2) = (*a, *b);
a2 = f(a2, b2);
b2 = f(b2, a2);
a2 += f(b2, *c);
b2 += f(*c, *d);
a2 += f(*d, *e);
b2 += f(*e, *f2);
a2 += f(*f2, *g);
*a = a2;
*b = b2;
}
}
#[cfg(feature = "rayon")]
fn zipping_with_rayon(
v: &mut Vec<f64>,
v1: &mut Vec<f64>,
v2: &mut Vec<f64>,
v3: &mut Vec<f64>,
v4: &mut Vec<f64>,
v5: &mut Vec<f64>,
v6: &mut Vec<f64>,
) {
let f = |x, y| x * 3.6321 + 42314.0 * y;
v.par_iter_mut()
.zip(v1.par_iter_mut())
.zip(v2.par_iter_mut())
.zip(v3.par_iter_mut())
.zip(v4.par_iter_mut())
.zip(v5.par_iter_mut())
.zip(v6.par_iter_mut())
.for_each(|((((((a, b), c), d), e), f2), g)| {
let (mut a2, mut b2) = (*a, *b);
a2 = f(a2, b2);
b2 = f(b2, a2);
a2 += f(b2, *c);
b2 += f(*c, *d);
a2 += f(*d, *e);
b2 += f(*e, *f2);
a2 += f(*f2, *g);
*a = a2;
*b = b2;
});
}
fn zip(c: &mut Criterion) {
let bench = Fun::new("Benchmark", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
b.iter(|| {
benchmark(&mut v, &mut v1);
})
});
let unnecessary_zipping = Fun::new("Unnecessary Zipping", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
let mut v2 = make_random_vec::<f64>();
let mut v3 = make_random_vec::<f64>();
let mut v4 = make_random_vec::<f64>();
let mut v5 = make_random_vec::<f64>();
let mut v6 = make_random_vec::<f64>();
b.iter(|| {
unnecessary_zipping(&mut v, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6);
})
});
let unnecessary_zipping_with_map = Fun::new("Unnecessary Zipping With Map", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
let mut v2 = make_random_vec::<f64>();
let mut v3 = make_random_vec::<f64>();
let mut v4 = make_random_vec::<f64>();
let mut v5 = make_random_vec::<f64>();
let mut v6 = make_random_vec::<f64>();
b.iter(|| {
unnecessary_zipping_with_map(
&mut v, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6,
);
})
});
let unnecessary_zipping_with_struct =
Fun::new("Unnecessary Zipping With Struct", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
let mut v2 = make_random_vec::<f64>();
let mut v3 = make_random_vec::<f64>();
let mut v4 = make_random_vec::<f64>();
let mut v5 = make_random_vec::<f64>();
let mut v6 = make_random_vec::<f64>();
b.iter(|| {
unnecessary_zipping_with_struct(
&mut v, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6,
);
})
});
let zipping = Fun::new("Zipping", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
let mut v2 = make_random_vec::<f64>();
let mut v3 = make_random_vec::<f64>();
let mut v4 = make_random_vec::<f64>();
let mut v5 = make_random_vec::<f64>();
let mut v6 = make_random_vec::<f64>();
b.iter(|| {
zipping(&mut v, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6);
})
});
#[cfg(feature = "rayon")]
let zipping_with_rayon = Fun::new("Zipping With Rayon", move |b, _| {
let mut v = make_random_vec::<f64>();
let mut v1 = make_random_vec::<f64>();
let mut v2 = make_random_vec::<f64>();
let mut v3 = make_random_vec::<f64>();
let mut v4 = make_random_vec::<f64>();
let mut v5 = make_random_vec::<f64>();
let mut v6 = make_random_vec::<f64>();
b.iter(|| {
zipping_with_rayon(&mut v, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6);
})
});
let fns = vec![
bench,
unnecessary_zipping,
unnecessary_zipping_with_map,
unnecessary_zipping_with_struct,
zipping,
#[cfg(feature = "rayon")]
zipping_with_rayon,
];
c.bench_functions("zip", fns, ());
}
criterion_group!(benches, zip);
criterion_main!(benches);