计算两个 __m256i 变量的元素之间的 logical_and (&&) 的最快方法是什么,寻找任何一对非零元素
What is the fastest way to calculate the logical_and (&&) between elements of two __m256i variables, looking for any pair of non-zero elements
据我所知,C++ 中的整数可以像布尔值一样处理,我们可以有这样的代码:
int a = 6, b = 10;
if (a && b) do something ---> true as both a and b are non-zero
现在,假设我们有:
__m256i a, b;
我需要对 __m256i 中的所有 4 个长变量应用 logical_and (&&),如果一对非零,则 return 为真。我的意思是:
(a[0] && b[0]) || (a[1] && b[1]) || ...
我们是否有用于此目的的 AVX 或 AVX2 快速代码?
我找不到任何用于此目的的直接指令,而且肯定地,使用按位和 (&) 也不一样。任何帮助将不胜感激。
您可以巧妙地将 vpcmpeqq
与 vptest
结合起来:
__m256i mask = _mm256_cmpeq_epi64(a, _mm256_set1_epi64x(0));
bool result = ! _mm256_testc_si256(mask, b);
当且仅当(~mask & b) != 0
或
时result
为真
((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
这相当于你想要的。
Godbolt-link(玩转 a
和 b
):https://godbolt.org/z/aTjx7vMKd
如果result
是循环条件,编译器当然应该直接执行jb
/jnb
指令而不是setnb
.
据我所知,C++ 中的整数可以像布尔值一样处理,我们可以有这样的代码:
int a = 6, b = 10;
if (a && b) do something ---> true as both a and b are non-zero
现在,假设我们有:
__m256i a, b;
我需要对 __m256i 中的所有 4 个长变量应用 logical_and (&&),如果一对非零,则 return 为真。我的意思是:
(a[0] && b[0]) || (a[1] && b[1]) || ...
我们是否有用于此目的的 AVX 或 AVX2 快速代码?
我找不到任何用于此目的的直接指令,而且肯定地,使用按位和 (&) 也不一样。任何帮助将不胜感激。
您可以巧妙地将 vpcmpeqq
与 vptest
结合起来:
__m256i mask = _mm256_cmpeq_epi64(a, _mm256_set1_epi64x(0));
bool result = ! _mm256_testc_si256(mask, b);
当且仅当(~mask & b) != 0
或
result
为真
((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
这相当于你想要的。
Godbolt-link(玩转 a
和 b
):https://godbolt.org/z/aTjx7vMKd
如果result
是循环条件,编译器当然应该直接执行jb
/jnb
指令而不是setnb
.