5

我正在尝试使用 SSE 指令进行一些图像过滤。我正在使用的图像每个像素有一个字节(255 灰度),我需要使用大于比较来比较无符号打包字节。我查看了英特尔的手册,并且存在比较,但仅适用于有符号字节(PCMPGTB)。我怎样才能对无符号字节进行比较?提前致谢

4

4 回答 4

16

在 AVX-512 1之前,确实不可能直接进行无符号比较。

但是您可以将 -128 添加到每个值(或减去 128,或 XOR 0x80,或类似的)。这会将 0 变为 -128,将 255 变为 127,其他值变为介于两者之间的值;结果是您从比较中获得了正确的结果。

将其扩展为单词也应该有效,但听起来有点慢,因为您完成了每条指令的一半工作。

_mm_cmpgt_epu8(a, b) = _mm_cmpgt_epi8(
        _mm_xor_epi8(a, _mm_set1_epi8(-128)),  // range-shift to unsigned
        _mm_xor_epi8(b, _mm_set1_epi8(-128)))

pxor可以在比某些 CPU 上更多的执行端口上运行paddb,因此如果您需要这样做,它通常是最佳选择。XOR 是无进位加法,加减 0x80 的进位输出到每个字节元素的顶部。


脚注 1:使用 AVX-512BW:

vpcmpub它将比较谓词作为立即数,例如cmpps. _mm_cmp[eq|ge|gt|le|lt|neq]_epu8_mask比较到掩码而不是另一个向量,因为这就是 AVX-512 比较指令的工作方式。例如
__mmask16 _mm_cmpgt_epu8_mask (__m128i a, __m128i b) 在英特尔的内在指南中

于 2014-06-15T22:34:47.487 回答
5

无符号比较 (a >= b) 与 maxu( a, b ) == a 相同,因此您可以使用

_mm_cmpeq_epi8( a, _mm_max_epu8(a,b))   -->   a >= b  "cmpge_epu8(a,b)"

如果您需要一个 <>比较,您需要反转结果,此时 Alcaro 的方法可能同样好(尽管该方法需要一个寄存器来携带一个用于反转的常数)。但是对于 a >=or<=比较,这肯定更好(因为没有 _mm_cmple_epi8 或 _mm_cmpge_epi8 可供使用,即使在将无符号转换为有符号范围之后)。

于 2015-02-07T14:08:54.353 回答
2

对@greggo 的解决方案提出一个小而重要的改进:

maxu( a, b ) == a

有一个缺点,因为您必须在 maxu 比较之前备份“a”,从而导致补充操作,如下所示:

movq mmc, mma
pmaxu mma, mmb
pcmpeq mma, mmc

minu( a, b ) == b

给出完全相同的效果,但保留了相等检查的运算符:

pminu mma, mmb
pcmpeq mma, mmb

收益是显着的:只需 2 次操作而不是 3 次。

于 2017-09-25T10:51:00.030 回答
1

除了比较打包的无符号字节之外,不可能做得更好,我已经将字节解包为单词(因为它们是肯定的,就像从无符号到有符号的转换以及从字节到单词的扩展)并使用 PCMPGTB 比较它们。

于 2013-04-27T19:17:56.347 回答