代码之家  ›  专栏  ›  技术社区  ›  Lautaro

SSE比较压缩的无符号字节

  •  5
  • Lautaro  · 技术社区  · 11 年前

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

    4 回复  |  直到 7 年前
        1
  •  16
  •   Peter Cordes Steve Bohrer    3 年前

    在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 可以在比 paddb 在一些CPU上,所以如果需要这样做,这通常是最好的选择。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

        2
  •  5
  •   greggo    9 年前

    无符号比较(a>=b)与maxu(a, 这样你就可以使用

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

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

        3
  •  2
  •   Zoltán Bíró    7 年前

    对@greggos解决方案提出了一个小但重要的增强: 这个

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

        4
  •  1
  •   Lautaro    11 年前

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