【问题标题】:SSE Compare Packed Unsigned BytesSSE 比较压缩无符号字节
【发布时间】:2013-04-25 00:51:00
【问题描述】:

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

【问题讨论】:

  • 您还可以利用“max”和“min”运算符,它们可用于无符号字节 [ 但不适用于有符号字节。这就是当指令集需要花费数十位将指令与遗留操作码区分开来回到 80 年代时的结果,并且只能负担一些对实际操作进行编码的结果......] 还有 u8 的饱和加减法,有时可以对通常用无符号比较描述的操作产生影响。如果您喜欢解决难题,那么编程 SSE 肯定会更有趣。

标签: x86 comparison unsigned sse


【解决方案1】:

在 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:

vpcmpub 将比较谓词作为立即数,如cmpps_mm_cmp[eq|ge|gt|le|lt|neq]_epu8_mask 比较掩码而不是另一个向量,因为这就是 AVX-512 比较指令的工作方式。例如
__mmask16 _mm_cmpgt_epu8_mask (__m128i a, __m128i b)in Intel's intrinsics guide

【讨论】:

  • 这是利用有符号比较作为无符号使用的“转到”方法,反之亦然 - 绝对比在比较之前扩展到 16 位的(当前接受的答案)方法要好得多。但我认为,鉴于字节“maxu”的可用性,我的优势在于,特别是对于 >= 比较而不是 >.
【解决方案2】:

无符号比较 (a >= b) 等同于 maxu( a, b ) == a, 所以你可以使用

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

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

【讨论】:

  • 简单而精彩。谢谢你的主意。我会好好利用它的。
【解决方案3】:

对@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 次。

【讨论】:

  • 或者:pmaxu mmb,mma,然后是 pcmpeq mmb,mma。无论哪种方式,您都会丢弃其中一个原始操作数。
【解决方案4】:

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

【讨论】:

  • 在我看来,要执行 cmp**_epu8,这需要 7 个操作:四个“解包”,两个 cmp**_epi16,然后是一个包,并且使用的寄存器比其他答案多得多.
猜你喜欢
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 2014-01-28
  • 1970-01-01
  • 2021-02-11
  • 2019-10-24
  • 1970-01-01
相关资源
最近更新 更多