在 __m128i 向量上水平检查零?

Posted

技术标签:

【中文标题】在 __m128i 向量上水平检查零?【英文标题】:Check for zeros horizontally across __m128i vector? 【发布时间】:2014-04-21 21:34:16 【问题描述】:

我有几个包含 32 位无符号整数的 __m128i 向量,我想检查这 4 个整数中是否有任何一个为零。

我了解如何“聚合”多个 __m128i 向量,但最终我仍会得到一个 __m128i 向量,然后我需要对其进行水平检查。

如何在最后一个向量上执行最终的水平零检查?

编辑 我使用的是 Intel 内在函数,而不是内联汇编

【问题讨论】:

您是否尝试过使用测试内在函数?比较 + 测试可能会做你想做的事。 【参考方案1】:

不要这样做。尽可能避免水平操作;这对向量代码的性能来说是致命的。

相反,将向量与零向量进行比较,然后使用 PMOVMSKB 在 GPR 中获取掩码。如果该掩码不为零,则向量的至少一条车道为零:

__m128i yourVector;
__m128i zeroVector = _mm_set1_epi32(0);

if (_mm_movemask_epi8(_mm_cmpeq_epi32(yourVector,zeroVector))) 
    // at least one lane of your vector is zero.

如果您想采用 SSE4.1,也可以使用 PTEST。


从表面上看这个问题,如果你真的需要做一个水平的并且出于某种原因,那就是 movhlps + andps + shufps + andps。但不要那样做。

【讨论】:

@RaymondChen 但这很容易倒过来。 @RaymondChen:正如 Mystical 所说,任何通道零都与 !(所有通道非零)相同,这是 PTEST 可以做到的。 @user997112 不。求和需要将它们实际相加。在 AVX512 之前不会有添加的水平缩减指令。 @StephenCanon 听起来这是对较大向量的缩减。最后,您仍然必须减少单个向量。但在这种情况下,它可能不是性能关键,因为它是 O(N) 操作的 O(1)。 @StephenCanon 如果我编写水平向量代码,它总是在循环之后,一旦所有并行处理完成并且我需要聚合结果。

以上是关于在 __m128i 向量上水平检查零?的主要内容,如果未能解决你的问题,请参考以下文章

_mm_shuffle_ps() 等价于整数向量 (__m128i)?

SSE/AVX 向量类型的差异

计算两个 _m128i SIMD 向量之间的匹配字节数

在 sse 向量 m128 中找到最大浮点数

SSE中的等零指令[重复]

SIMD 零向量测试