use criterion::{black_box, criterion_group, criterion_main, Criterion};
const PRIME: u64 = 0x00000100000001b3;
const OFFSET: u64 = 0xcbf29ce484222325;
#[inline]
fn hash(hash: u64, value: u64) -> u64 {
(hash ^ value) * PRIME
}
fn baseline(input: &[u64]) -> u64 {
let mut h = OFFSET;
let mut i: usize = 0;
while i < input.len() {
h = hash(h, input[i]);
i = i + 1;
}
h
}
fn unrolled(input: &[u64]) -> u64 {
let mut h: u64 = OFFSET;
let mut i: usize = 0;
while i < input.len() {
h = hash(h, input[i]);
h = hash(h, input[i + 1]);
h = hash(h, input[i + 2]);
h = hash(h, input[i + 3]);
h = hash(h, input[i + 4]);
i = i + 5;
}
h
}
fn temp(input: &[u64]) -> u64 {
let mut h: u64 = OFFSET;
let mut i: usize = 0;
while i < input.len() {
let mut tmp: u64 = input[i];
tmp = hash(tmp, input[i + 1]);
tmp = hash(tmp, input[i + 2]);
tmp = hash(tmp, input[i + 3]);
tmp = hash(tmp, input[i + 4]);
h = hash(h, tmp);
i = i + 5;
}
h
}
fn laned(input: &[u64]) -> u64 {
let mut h1: u64 = OFFSET;
let mut h2: u64 = OFFSET;
let mut h3: u64 = OFFSET;
let mut h4: u64 = OFFSET;
let mut h5: u64 = OFFSET;
let mut i: usize = 0;
while i < input.len() {
h1 = hash(h1, input[i]);
h2 = hash(h2, input[i + 1]);
h3 = hash(h3, input[i + 2]);
h4 = hash(h4, input[i + 3]);
h5 = hash(h5, input[i + 4]);
i = i + 5;
}
hash(hash(hash(hash(h1, h2), h3), h4), h5)
}
use rand::Rng;
fn ilp_benchmark(c: &mut Criterion) {
let mut rng = rand::thread_rng();
let mut input: [u64; 100000] = [0; 100000];
for i in 0..input.len() {
input[i] = rng.gen::<u64>();
}
c.bench_function("baseline", |b| b.iter(|| black_box(baseline(&input))));
c.bench_function("unrolled", |b| b.iter(|| black_box(unrolled(&input))));
c.bench_function("temp", |b| b.iter(|| black_box(temp(&input))));
c.bench_function("laned", |b| b.iter(|| black_box(laned(&input))));
}
criterion_group!(benches, ilp_benchmark);
criterion_main!(benches);