计算两个 __m256i 变量的元素之间的逻辑与 (&&) 的最快方法是什么,寻找任何一对非零元素

Moj*_*deh 6 c++ simd avx avx2 logical-and

据我所知,C++中的整数可以像布尔值一样对待,我们可以有这样的代码:

int a = 6, b = 10;
if (a && b) do something ---> true as both a and b are non-zero
Run Code Online (Sandbox Code Playgroud)

现在,假设我们有:

__m256i a, b;
Run Code Online (Sandbox Code Playgroud)

我需要对 __m256i 中的所有 4 个长变量应用逻辑与 (&&),如果一对非零则返回 true。我的意思是:

(a[0] && b[0]) || (a[1] && b[1]) || ...
Run Code Online (Sandbox Code Playgroud)

我们是否有用于此目的的 AVX 或 AVX2 快速代码?

我找不到任何直接的指令用于此目的,并且肯定,使用按位与 (&) 也是不一样的。

cht*_*htz 8

您可以巧妙地将 avpcmpeqq与 a结合起来vptest

__m256i mask = _mm256_cmpeq_epi64(a, _mm256_set1_epi64x(0));
bool result = ! _mm256_testc_si256(mask, b);
Run Code Online (Sandbox Code Playgroud)

result且仅当(~mask & b) != 0或者

((a[i]==0 ? 0 : -1) & b[i]) != 0 // for some i
// equivalent to
((a[i]==0 ? 0 : b[i])) != 0      // for some i
// equivalent to
a[i]!=0 && b[i]!=0               // for some i
Run Code Online (Sandbox Code Playgroud)

这相当于你想要的。

Godbolt-link(使用ab): https: //godbolt.org/z/aTjx7vMKd

ifresult是循环条件,编译器当然应该直接执行jb/jnb指令而不是setnb