Open xxchan opened 2 years ago
And when I change iter
to calculate a sum, the results changed again...
test tests::bench1 ... bench: 161,524 ns/iter (+/- 4,970)
test tests::bench2_1 ... bench: 193,444 ns/iter (+/- 9,360)
test tests::bench2_2 ... bench: 192,883 ns/iter (+/- 7,177)
test tests::bench3_1 ... bench: 162,645 ns/iter (+/- 7,508)
test tests::bench3_2 ... bench: 176,655 ns/iter (+/- 8,012)
#![feature(test)]
#![feature(core_intrinsics)]
#![feature(generators, generator_trait)]
extern crate test;
pub struct MarkedVec {
v: Vec<i32>,
vis: Vec<bool>,
}
impl MarkedVec {
pub fn iter(&self) -> MarkedVecIter<'_> {
MarkedVecIter::<'_> {
v: &self.v,
vis: &self.vis,
pos: 0,
}
}
}
pub struct MarkedVecIter<'a> {
v: &'a [i32],
vis: &'a [bool],
pos: usize,
}
impl<'a> Iterator for MarkedVecIter<'a> {
type Item = i32;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
while self.pos < self.v.len() {
unsafe {
if *self.vis.get_unchecked(self.pos) {
let item = *self.v.get_unchecked(self.pos);
self.pos += 1;
return Some(item);
}
self.pos += 1;
}
}
None
}
}
#[no_mangle]
pub fn g(v: i32) -> i32 {
v + v + v
}
pub fn iter1(mv: &MarkedVec) -> i32 {
let mut res = 0;
let n = mv.v.len();
for i in 0..n {
unsafe {
if *mv.vis.get_unchecked(i) {
res += g(*mv.v.get_unchecked(i));
}
}
}
res
}
pub fn iter2_1(mv: &MarkedVec) -> i32 {
let mut res = 0;
for x in mv.iter() {
res += g(x);
}
res
}
pub fn iter2_2(mv: &MarkedVec) -> i32 {
let mut res = 0;
mv.iter().for_each(|x| res += g(x));
res
}
pub fn iter3_1(mv: &MarkedVec) -> i32 {
let mut res = 0;
for x in
mv.v.iter()
.zip(&mv.vis)
.filter_map(|(x, v)| if *v { Some(*x) } else { None })
{
res += g(x);
}
res
}
pub fn iter3_2(mv: &MarkedVec) -> i32 {
let mut res = 0;
mv.v.iter()
.zip(&mv.vis)
.filter_map(|(x, v)| if *v { Some(*x) } else { None })
.for_each(|x| res += g(x));
res
}
pub fn no_op(mv: &MarkedVec) {}
#[inline(never)]
fn init(mv: &mut MarkedVec, n: usize, x: i32, y: i32) {
mv.v.clear();
for i in 0..n {
mv.v.push(x + i as i32);
}
mv.vis.clear();
for i in 0..n {
mv.vis.push(i % y as usize == 0);
}
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[test]
fn it_works() {}
#[bench]
fn bench1(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
iter1(&mv)
});
}
#[bench]
fn bench2_1(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
iter2_1(&mv)
});
}
#[bench]
fn bench2_2(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
iter2_2(&mv)
});
}
#[bench]
fn bench3_1(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
iter3_1(&mv)
});
}
#[bench]
fn bench3_2(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
iter3_2(&mv)
});
}
#[bench]
fn bench_no_op(b: &mut Bencher) {
let n = test::black_box(100000);
let mut mv = MarkedVec {
v: Vec::with_capacity(n),
vis: Vec::with_capacity(n),
};
b.iter(|| {
init(&mut mv, n, 3, 2);
no_op(&mv);
});
}
}
g is
test::black_box