SSE内在的int16 [8]提取每个元素的符号

Mic*_*ele 7 c x86 sse sign simd

我正在使用SSE内部函数.我有一个__m128i代表一个8个有符号短(16位)值的数组.

是否有函数来获取每个元素的符号?

EDIT1:可以像这样使用的东西:

short tmpVec[8];
__m128i tmp, sgn;

for (i-0;i<8;i++)
    tmp.m128i_i16[i] = tmpVec[i]

sgn = _mm_sign_epi16(tmp);
Run Code Online (Sandbox Code Playgroud)

当然"_mm_sign_epi16"不存在,所以这就是我要找的东西.

逐个元素地执行它有多慢?

EDIT2:所需行为:1表示正值,0表示零,-1表示负值.

谢谢

Pau*_*l R 13

您可以使用最小/最大操作来获得所需的结果,例如

inline __m128i _mm_sgn_epi16(__m128i v)
{
    v = _mm_min_epi16(v, _mm_set1_epi16(1));
    v = _mm_max_epi16(v, _mm_set1_epi16(-1));
    return v;
}
Run Code Online (Sandbox Code Playgroud)

这可能比明确地与零+移位+组合结果进行比较更有效.

请注意,_mm_sign_epi16SSSE3中已存在一个内在函数(PSIGNW- 请参阅tmmintrin.h),其行为有所不同,因此我将所需函数的名称更改为_mm_sgn_epi16._mm_sign_epi16但是,当SSSE3可用时,使用可能会更有效,因此您可以执行以下操作:

inline __m128i _mm_sgn_epi16(__m128i v)
{
#ifdef __SSSE3__
    v = _mm_sign_epi16(_mm_set1_epi16(1), v); // use PSIGNW on SSSE3 and later
#else
    v = _mm_min_epi16(v, _mm_set1_epi16(1));  // use PMINSW/PMAXSW on SSE2/SSE3.
    v = _mm_max_epi16(v, _mm_set1_epi16(-1));
#endif
    return v;
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,两个`_mm_set1_epi16可以优化为`_mm_cmpeq_epi16(v,v)`和`_mm_srl_epi16(mm_cmpeq_epi16(v,v),15)`.这可以避免域停顿并仅编码为1或2条指令. (2认同)