__m128i变量是零吗?

Meh*_*dad 11 c c++ sse intel simd

如何测试__m128i变量在SSE-2和更早版本的处理器上是否具有任何非零值?

Nec*_*lis 12

在SSE2中,您可以:

__m128i zero = _mm_setzero_si128();
if(_mm_movemask_epi8(_mm_cmpeq_epi32(x,zero)) == 0xFFFF)
{
    //the code...
}
Run Code Online (Sandbox Code Playgroud)

这将测试四个int与零然后为每个字节返回一个掩码,因此每个对应的位偏移量int将为0,4,8 和12,但上述测试将捕获是否设置了任何位,然后如果保留如果需要,你可以直接使用更细粒度的部件.

  • 在其他优秀的答案中有一个错误 - 如果你要检查所有零,它应该是`if(_mm_movemask_epi8(_mm_cmpeq_epi32(x,zero))== 0xFFFF)`.这是因为`_mm_cmpeq_epi32`将int设置为全1,而不是全0,如果它等于零,则`_mm_movemask_epi8`根据参数中每个字节的最高有效位设置前16位.希望作者可以编辑答案 - 我试过但被拒绝了. (3认同)
  • +1,它比我的好.:)我从来没有使用过movemask指令,所以我不知道你能做到这一点.XD (2认同)
  • 我以不同的方式阅读原始问题.您的代码执行您所说的操作,即检查所有四个32位值是否为非零.我将问题解释为"任何"值非零,如问题正文中所述,或相反,如果它们全部为零,如问题的标题和OP对Brett Hale的澄清.如果这是需要的(这是我的项目所需要的,这导致我找到这个问题),那么你需要测试0xFFFF. (2认同)

Ant*_*nio 5

为了完整起见,SSE4 可以使用_mm_testz_si128

const bool isAllZero = _mm_testz_si128(a,a);
Run Code Online (Sandbox Code Playgroud)

请注意,当所有位都为零时,这是正确的

  • 这实际上稍微快一点,并且不需要全零寄存器来测试。`ptest` / `jz` 是 2 + 1 uop(不是宏熔断器)。`pcmpeq`(1uop)/`pmovmsk`(1uop)/`和0xffff`(1uop)/`cmp 0xffff/je`(1uop)。如果您正在测试其他情况(*任何*零元素,而不是*所有*零元素),则它们在当前的 Intel 和 AMD CPU 上的性能大致相同:`ptest`/`jnz`(3 uops)与. `pcmpeq` / `pmovmsk` / `test/jnz` (3 uops)。 (2认同)