使用 Rust 自动矢量化

xxx*_*222 4 simd rust auto-vectorization

我是 rust/SIMD 新手,我有以下代码片段作为我的程序的瓶颈,我想知道我是否可以利用它的自动向量化功能

fn is_subset(a: Vec<i64>, b: Vec<i64>) -> bool {
    for i in 0..a.len() {
        if (a[i] & !b[i]) != 0 {
            return false;
        }
    }
    true
}
Run Code Online (Sandbox Code Playgroud)

我还有另一种编写方法(使用迭代器,因此可以预先知道行程计数),这会创建自动向量化吗?

fn is_subset(a: Vec<i64>, b: Vec<i64>) -> bool {
    return a.iter().zip(b.iter()).all(|(x, y)| x & y == *x)
}

Run Code Online (Sandbox Code Playgroud)

Pet*_*des 8

LLVM(和 GCC)不知道如何自动矢量化无法预先计算行程计数的循环。这排除了像这样的搜索循环。

ICC classic 可以自动向量化此类循环,但它是一个 C/C++ 编译器,没有 Rust 前端。

也许您唯一的希望是手动循环数组的 2、4 或 8 元素块,根据所有这些元素无分支地计算您的条件。如果幸运的话,LLVM 可能会将其转换为一个 SIMD 向量上的操作。因此,在更大的循环中使用该内部循环可能会导致编译器生成矢量化 asm,例如使用 AVX vptest(根据a AND (not b)具有任何非零位的按位设置 CF)。

即针对特定向量宽度手动表达源中 SIMD 元素的“展开”。

相关回复:让编译器使用 x86 自动矢量化ptest

如果整个数组足够小,则编译器愿意对整个数组进行无分支缩减(将布尔结果或运算在一起。如果针对 x86 进行编译,您会希望在循环中出现类似pandn/ 的asm,并在最后进行水平缩减,因此请查看和 的交集中是否设置了任何位poranot b

i64每个 16 字节向量只有 2 个元素,因此编译器必须找到一个好的策略,以便自动向量化有利可图,尤其是在 64 位机器上。拥有 32 字节向量使其更具吸引力。