Merge branch 'bench' into 'master'

Add Benches

See merge request tspiteri/fixed!2
This commit is contained in:
Trevor Spiteri 2019-08-03 21:45:39 +00:00
commit 508949c293
2 changed files with 188 additions and 0 deletions

View File

@ -17,6 +17,7 @@ keywords = ["mathematics", "numerics"]
categories = ["algorithms", "data-structures", "no-std", "science"]
license = "MIT/Apache-2.0"
edition = "2018"
autobenches = false
[features]
f16 = ["half"]
@ -34,5 +35,16 @@ version = "1.0.25"
default-features = false
optional = true
[dev-dependencies]
rand = { version = "0.6", default-features = false }
rand_xoshiro = "0.2"
criterion = "0.2"
num-traits = { version = "0.2", default-features = false }
[package.metadata.docs.rs]
features = ["f16", "serde"]
[[bench]]
name = "bench_main"
harness = false

176
benches/bench_main.rs Normal file
View File

@ -0,0 +1,176 @@
use {
criterion::{
black_box, criterion_group, criterion_main, Bencher, Benchmark, Criterion, Throughput,
},
fixed::{
sealed::{Fixed, Int},
types::*,
},
num_traits::{One, Zero},
rand::{
distributions::{Distribution, Standard},
Rng,
},
rand_xoshiro::{rand_core::SeedableRng, Xoshiro256Plus},
std::convert::TryInto,
};
const SEED: u64 = 42_069;
const DATASET_SIZE: usize = 10_000;
fn gen_non_zero<T, R>(rng: &mut R) -> T
where
R: Rng + ?Sized,
T: Zero + One + PartialEq,
Standard: Distribution<T>,
{
let value: T = rng.gen();
if value != T::zero() {
return value;
} else {
T::one()
}
}
fn gen_tuple_dataset<T>(cap: usize) -> Vec<(T, T)>
where
T: Zero + One + PartialEq,
Standard: Distribution<T>,
{
let mut rng: Xoshiro256Plus = Xoshiro256Plus::seed_from_u64(SEED);
(0..cap)
.map(|_| (rng.gen(), gen_non_zero(&mut rng)))
.collect()
}
fn fixed_point_op<F, B, O>(bencher: &mut Bencher, op: O)
where
F: Fixed<Bits = B>,
B: Int + Zero + One + PartialEq,
Standard: Distribution<F::Bits>,
O: Fn(F, F) -> F,
{
let bits_dataset: Vec<(F::Bits, F::Bits)> = gen_tuple_dataset(DATASET_SIZE);
let fixed_dataset: Vec<(F, F)> = bits_dataset
.into_iter()
.map(|(l, r)| (Fixed::from_bits(l), Fixed::from_bits(r)))
.collect();
bencher.iter(|| {
for (l, r) in &fixed_dataset {
let r = op(*l, *r);
black_box(r);
}
});
}
fn primitive_op<P, O>(b: &mut Bencher, op: O)
where
Standard: Distribution<P>,
P: Copy + PartialEq + Zero + One,
O: Fn(P, P) -> P,
{
let primitive_dataset: Vec<(P, P)> = gen_tuple_dataset(DATASET_SIZE);
b.iter(|| {
for (l, r) in &primitive_dataset {
let sum = op(*l, *r);
black_box(sum);
}
});
}
macro_rules! create_bench {
($bench:ident, $name:expr, $op:expr) => {
pub(crate) fn $bench(c: &mut Criterion) {
c.bench(
&$name.to_owned(),
// We only measure the overhead for the 64 bit test because
// we found that the overhead is consistant accross sizes.
Benchmark::new("benchmark overhead", move |b| {
let f64_dataset: Vec<(f64, f64)> = gen_tuple_dataset(DATASET_SIZE);
b.iter(|| {
for (l, _) in &f64_dataset {
black_box(l);
}
});
})
.with_function("u128", move |b| {
primitive_op::<u128, _>(b, $op);
})
.with_function("i128", move |b| {
primitive_op::<i128, _>(b, $op);
})
.with_function("FixedU128", move |b| {
fixed_point_op::<U64F64, _, _>(b, $op);
})
.with_function("FixedI128", move |b| {
fixed_point_op::<I64F64, _, _>(b, $op);
})
.with_function("f64", move |b| {
primitive_op::<f64, _>(b, $op);
})
.with_function("u64", move |b| {
primitive_op::<u64, _>(b, $op);
})
.with_function("i64", move |b| {
primitive_op::<i64, _>(b, $op);
})
.with_function("FixedU64", move |b| {
fixed_point_op::<U32F32, _, _>(b, $op);
})
.with_function("FixedI64", move |b| {
fixed_point_op::<I32F32, _, _>(b, $op);
})
.with_function("f32", move |b| {
primitive_op::<f32, _>(b, $op);
})
.with_function("u32", move |b| {
primitive_op::<u32, _>(b, $op);
})
.with_function("i32", move |b| {
primitive_op::<i32, _>(b, $op);
})
.with_function("FixedU32", move |b| {
fixed_point_op::<U16F16, _, _>(b, $op);
})
.with_function("FixedI32", move |b| {
fixed_point_op::<I16F16, _, _>(b, $op);
})
.with_function("u16", move |b| {
primitive_op::<u16, _>(b, $op);
})
.with_function("i16", move |b| {
primitive_op::<i16, _>(b, $op);
})
.with_function("FixedU16", move |b| {
fixed_point_op::<U8F8, _, _>(b, $op);
})
.with_function("FixedI16", move |b| {
fixed_point_op::<I8F8, _, _>(b, $op);
})
.with_function("u8", move |b| {
primitive_op::<u8, _>(b, $op);
})
.with_function("i8", move |b| {
primitive_op::<i8, _>(b, $op);
})
.with_function("FixedU8", move |b| {
fixed_point_op::<U4F4, _, _>(b, $op);
})
.with_function("FixedI8", move |b| {
fixed_point_op::<I4F4, _, _>(b, $op);
})
.throughput(Throughput::Elements(DATASET_SIZE.try_into().unwrap())),
);
}
};
}
create_bench!(bench_add, "add", |l, r| l + r);
create_bench!(bench_sub, "sub", |l, r| l - r);
create_bench!(bench_mul, "mul", |l, r| l * r);
create_bench!(bench_div, "div", |l, r| l / r);
criterion_group!(benches, bench_add, bench_sub, bench_mul, bench_div);
criterion_main!(benches);