最佳SSE无符号8位比较

Pau*_*l R 7 c x86 sse simd sse4

我试图找到使用SSE执行8位无符号比较的最多方法(直到SSE 4.2).

我正在研究的最常见的情况是比较> 0U,例如

_mm_cmpgt_epu8(v, _mm_setzero_si128())                // #1
Run Code Online (Sandbox Code Playgroud)

(这当然也可以被认为是非零的简单测试.)

但我对更一般的情况也有点兴趣,例如

_mm_cmpgt_epu8(v1, v2)                                // #2
Run Code Online (Sandbox Code Playgroud)

第一种情况可以使用各种不同的方法用2条指令实现,例如与0比较然后反转结果.第二种情况通常需要3条指令,例如从两个操作数中减去128并执行带符号的比较.(有关各种3种指令解决方案,请参阅此问题.)

我理想的是为#1提供单指令解决方案,为#2提供双指令解决方案.如果这些都不可能,那么我也对在现代英特尔CPU(Sandy Bridge,Ivy Bridge,Haswell)上哪种各样可能的2或3指令实现最有效的想法感兴趣.


到目前为止,案例#2的最佳实现:

    1. 比较等于无符号最大值和反转结果:

#define _mm_cmpgt_epu8(v0, v1) \ _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(v0, v1), v1), \ _mm_set1_epi8(-1))

两个算术指令+一个按位= 1.33吞吐量.

    1. 反转两个参数的符号位(==减去128)并使用带符号的比较:

#define _mm_cmpgt_epu8(v0, v1) \ _mm_cmpgt_epi8(_mm_xor_si128(v0, _mm_set1_epi8(-128)), \ _mm_xor_si128(v1, _mm_set1_epi8(-128)))

一个算术指令+两个按位= 1.16吞吐量.


案例#1的最佳实现,源自上面的案例#2实现:

  • 1.

#define _mm_cmpgtz_epu8(v0) \ _mm_andnot_si128(_mm_cmpeq_epi8(v0, _mm_set1_epi8(0)), \ _mm_set1_epi8(-1))

一个算术指令+一个按位= 0.83吞吐量.

  • 2.

#define _mm_cmpgtz_epu8(v0) \ _mm_cmpgt_epi8(_mm_xor_si128(v0, _mm_set1_epi8(-128)), \ _mm_set1_epi8(-128)))

一个算术指令+一个按位= 0.83吞吐量.

Erm*_*mIg 5

Simd 库中有一个示例:

    const __m128i K_INV_ZERO = SIMD_MM_SET1_EPI8(0xFF);//_mm_set1_epi8(-1);

    SIMD_INLINE __m128i NotEqual8u(__m128i a, __m128i b)
    {
        return _mm_andnot_si128(_mm_cmpeq_epi8(a, b), K_INV_ZERO);
    }

    SIMD_INLINE __m128i Greater8u(__m128i a, __m128i b)
    {
        return _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(a, b), a), K_INV_ZERO);
    }

    SIMD_INLINE __m128i GreaterOrEqual8u(__m128i a, __m128i b)
    {
        return _mm_cmpeq_epi8(_mm_max_epu8(a, b), a);
    }

    SIMD_INLINE __m128i Lesser8u(__m128i a, __m128i b)
    {
        return _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(a, b), a), K_INV_ZERO);
    }

    SIMD_INLINE __m128i LesserOrEqual8u(__m128i a, __m128i b)
    {
        return _mm_cmpeq_epi8(_mm_min_epu8(a, b), a);
    }
Run Code Online (Sandbox Code Playgroud)