SSE指令集:测试是否全部为0或1的最快方法是什么?

3
我已经开发了一个用于Windows的Mandelbrot生成器,并将其转换为使用SSE指令集。在普通算术中,为了检测迭代的结束,我会进行大于比较并退出。在SSE中,我可以使用_mm_cmpgt_pd / _mm_cmpgt_ps对整个向量进行比较,然而,这将为我关心的情况写入一个新的128位向量,带有全部为1的值。
我的问题是,是否有更有效的方法来检测所有1而不是检查2个打包的64 INTs? 或者,如果检测所有0更有效,则可以进行小于比较。以下是我当前拥有的代码:
_m128d CompareResult = Magnitude > EarlyOut;
const __m128i Tmp = *reinterpret_cast< __m128i* >( &CompareResult );
if ( Tmp.m128i_u64[ 0 ] == Tmp.m128i_u64[ 1 ] == -1 )
{
    break;
}

我希望找到更好的方法,因为我不喜欢这种强制类型转换,而且根据vTune分析,超过30%的迭代时间都花在了最后一行。我知道其中很大一部分是分支本身造成的,但我认为通过更好地检测0或1,可以减少这种情况。

谢谢


请参见:https://dev59.com/52kw5IYBdhLWcg3wDWIk - FrankH.
1个回答

7
假设您正在测试比较结果,那么您可以提取每个字节的 MS 位作为一个 16 位整数并进行测试,例如:
int mask = _mm_movemask_epi8((__m128i)CompareResult);
if (mask == 0xffff)
{
    // compare results are all "true"
}

请注意,这只是SSE中SIMD谓词的一种更普遍技术的一个例子。
mask == 0xffff // all "true"
mask == 0x0000 // all "false"
mask != 0xffff // any "false"
mask != 0x0000 // any "true"

1
我认为这也是最有效的解决方案。当使用128位数据时,可能需要将0xFF替换为0xFFFF。 - user1940376
如果您拥有SSE4(PTEST),请参见上面链接的问题。 - FrankH.
@FrankH:PTEST 在检查全零方面很有效,但我不确定它能否帮助检查全为一的情况? - Paul R
我认为“反转比较”的做法可以实现这个目的? - FrankH.
@FrankH:不幸的是,"not all bits equal to zero"并不等同于"all bits equal to one"。 - Paul R
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接