X86 SSE比较压缩无符号字节

X86 SSE比较压缩无符号字节,x86,comparison,unsigned,sse,X86,Comparison,Unsigned,Sse,我正在尝试使用SSE指令进行一些图像过滤。我正在使用的图像每像素有一个字节(255灰度),我需要使用大于比较的方法来比较无符号压缩字节。我查阅了英特尔的手册,比较结果是存在的,但只针对有符号字节(PCMPGTB)。如何对无符号字节进行此比较? 提前感谢在压缩无符号字节中不可能进行比比较更好的比较,我已经将字节解压成字(因为它们是有符号的,就像从无符号到有符号的转换以及从字节到字的扩展),并使用PCMPGTB对它们进行比较。直接进行无符号比较确实是不可能的,直到AVX-5121 但您可以在每个值上

我正在尝试使用SSE指令进行一些图像过滤。我正在使用的图像每像素有一个字节(255灰度),我需要使用大于比较的方法来比较无符号压缩字节。我查阅了英特尔的手册,比较结果是存在的,但只针对有符号字节(PCMPGTB)。如何对无符号字节进行此比较?
提前感谢

在压缩无符号字节中不可能进行比比较更好的比较,我已经将字节解压成字(因为它们是有符号的,就像从无符号到有符号的转换以及从字节到字的扩展),并使用PCMPGTB对它们进行比较。

直接进行无符号比较确实是不可能的,直到AVX-5121

但您可以在每个值上加-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:

它将比较谓词作为立即数,如
cmpps
<代码>比较到一个掩码而不是另一个向量,因为AVX-512比较指令就是这样工作的。e、 g.
无符号比较(a>=b)与maxu(a,b)相同,
所以你可以用

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

如果需要比较
,则需要反转结果,此时Alcaro的方法可能同样有效(尽管该方法需要一个寄存器来携带一个常量进行反转)。但是对于
=
建议对@greggo的解决方案进行一个小而重要的增强:

有一个缺点,因为您必须在最大值比较之前备份“a”,从而导致一个补充操作,类似于:

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

提供完全相同的效果,但保留相等性检查的运算符:

pminu mma, mmb
pcmpeq mma, mmb

收益非常显著:只需2个操作,而不是3个。

您还可以利用“max”和“min”运算符,这两个运算符可用于无符号字节[但不适用于有符号操作。这是一个指令集需要花费几十位将一条指令与80年代遗留操作码区分开来的结果,并且只能提供很少的位来编码实际操作…]u8还有饱和加法和减法,这有时会影响通常用无符号比较来描述的操作。如果你喜欢解决难题,编程SSE肯定更有趣。在我看来,要完成cmp**epu8,需要7个操作:四个“解包”,两个cmp**epi16,然后是一个包,还有我们这是一种“转到”方法,用于将有符号比较用作无符号比较,或将有符号比较用作无符号比较,反之亦然-肯定比(当前接受的答案)好得多在比较之前扩展到16位的方法。但我认为,考虑到字节的“maxu”可用性,我的方法将其边缘化,特别是对于>=比较而不是>。简单但出色。感谢你的想法。我会好好利用它。或者:pmaxu mmb,mma,然后是pcmpeq mmb,mma。无论哪种方法,你都会丢弃一个原始操作数。
minu( a, b ) == b
pminu mma, mmb
pcmpeq mma, mmb