假设我们想要快速查找数组中第一个非零元素的索引,可以这样做:
fn leading_zeros(arr: &[u32]) -> Option<usize> {
arr.iter().position(|&x| x != 0)
}
然而,rustc
会将这个过程编译成逐个检查的方式,可以在这里看到。通过使用 u128
类型每次检查四个单词,可以略微提高速度。在我的机器上,这样做的速度提升约为3倍。
fn leading_zeros_wide(arr: &[u32]) -> Option<usize> {
let (beg, mid, _) = unsafe { arr.align_to::<u128>() };
beg.iter().position(|&x| x != 0).or_else(|| {
let left = beg.len() + 4 * mid.iter().position(|&x| x != 0).unwrap_or(mid.len());
arr[left..].iter().position(|&x| x != 0).map(|p| p + left)
})
}
有没有什么方法可以让这个过程更快?
以下是我使用的基准测试,以确定3倍加速:
#![feature(test)]
extern crate test;
fn v() -> Box<[u32]> {
std::iter::repeat(0).take(1000).collect()
}
// Assume `leading_zeros` and `leading_zeros_wide` are defined here.
#[bench]
fn bench_leading_zeros(b: &mut test::Bencher) {
let v = test::black_box(v());
b.iter(|| leading_zeros(&v[3..]))
}
#[bench]
fn bench_leading_zeros_wide(b: &mut test::Bencher) {
let v = test::black_box(v());
b.iter(|| leading_zeros_wide(&v[3..]))
}
end
参数,因为切片arr[left..]
包含了那部分内容。 - MERTONmemx
crate 目前在memnechr
方面存在一个 bug(至少在 0.1.18 版本中)。 - MERTON[simd]
标签看到这个问题的)。 - Alex Guteniev