检查Vec<u8>以查看它是否全部为零?

我有很多 4KiB 缓冲区,它们有 50% 的机会只包含零值。非零缓冲区通常在缓冲区的早期有一个非零字节。

fn is_zero(buf: &Vec<u8>) -> bool {
    for byte in buf.into_iter() {
        if *byte != 0 {
            return false;
        }
    }
    return true;
}

这是检查 Rust 的一种高效方式--release吗?(我正在处理许多 GB 的数据。)

(在 C 版本中,我unsigned long long在检查之前将缓冲区强制转换为。考虑到 SSE 等,这可能不是我能做的最好的事情。)

回答

align_to可以将 的切片转换u8为 的切片u128,使比较更有效:

fn is_zero(buf: &[u8]) -> bool {
    let (prefix, aligned, suffix) = unsafe { buf.align_to::<u128>() };

    prefix.iter().all(|&x| x == 0)
        && suffix.iter().all(|&x| x == 0)
        && aligned.iter().all(|&x| x == 0)
}

在我的机器上运行一个简单的基准测试显示 16 倍的性能提升!

#![feature(test)]
extern crate test;

fn v() -> Vec<u8> {
    std::iter::repeat(0).take(1000000).collect()
}

fn is_zero(buf: &[u8]) -> bool {
    buf.into_iter().all(|&b| b == 0)
}

fn is_zero_aligned(buf: &[u8]) -> bool {
    let (prefix, aligned, suffix) = unsafe { buf.align_to::<u128>() };

    prefix.iter().all(|&x| x == 0)
        && suffix.iter().all(|&x| x == 0)
        && aligned.iter().all(|&x| x == 0)
}

#[bench]
fn bench_is_zero(b: &mut test::Bencher) {
    let v = test::black_box(v());
    b.iter(|| is_zero(&v[..]))
}

#[bench]
fn bench_is_zero_aligned(b: &mut test::Bencher) {
    let v = test::black_box(v());
    b.iter(|| is_zero_aligned(&v[..]))
}
running 2 tests
test tests::bench_is_zero         ... bench:     455,975 ns/iter (+/- 414)
test tests::bench_is_zero_aligned ... bench:      28,615 ns/iter (+/- 116)

根据您的机器,不同的整数类型 ( u64) 可能会产生更好的性能。

感谢 Rust Discord 服务器上的 @Globi 提出这个想法


以上是检查Vec&lt;u8&gt;以查看它是否全部为零?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>