在 __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 向量上水平检查零?的主要内容,如果未能解决你的问题,请参考以下文章