AVX512中是否有_mm512_sign_epi16(__m512i a,__m512i b)这样的函数

yue*_*ing 4 simd instruction-set intrinsics avx2 avx512

以下功能似乎在AVX512上不可用:

__m512i _mm512_sign_epi16 (__m512i a, __m512i b)
Run Code Online (Sandbox Code Playgroud)

它会很快面世还是有其他选择?

Pet*_*des 5

如果不需要调零部分,则只需要2条指令(和调零的寄存器):

您可以_mm512_movepi16_mask()将符号位放入掩码(的AVX512版本pmovmskb)中,并从零进行合并掩码减法,以基于另一个符号取向量。

#ifdef __AVX512BW__
// does *not* do anything special for signs[i] == 0, just negative / non-negative
__m512i  conditional_negate(__m512i target, __m512i signs) {
    __mmask32 negmask = _mm512_movepi16_mask(signs);
      // vpsubw target{k1}, 0, target
    __m512i neg = _mm512_mask_sub_epi16(target, negmask, _mm512_setzero_si512(), target);
    return neg;
}
#endif
Run Code Online (Sandbox Code Playgroud)

矢量- >掩模具有对SKYLAKE微架构-X 3周期的延迟(与vpmovw2mvptestmwvpcmpw),但使用掩模只具有另一个1个周期的延迟。因此,从输入到输出的延迟为:

  • signs-> SKX上的结果开始4个周期
  • target-> SKX上的结果开始1个周期(只是vpsubw从零开始屏蔽)。

同样要应用is-zero条件:您可以对向量执行的下一个操作零屏蔽或合并屏蔽,因此未使用的元素应该为零。

您需要比较创建另一个面具一个额外的,但你可能并不需要浪费第2个额外的指令,立刻应用。

如果您真的想构建一个自包含的vpsignw方法,我们可以做最后的零掩码,但这是4个内在函数,可编译为4条指令,并且吞吐量可能比@wim的min / max / multiply差。但这具有良好的关键路径延迟,在SKX上总共大约有5个周期(如果可以将最终的遮罩折叠成其他东西,则为4个周期)。关键路径是迹象->遮罩,然后是遮罩子。signs-> nonzeromask可以与任何一个并行运行。

__m512i  mm512_psignw(__m512i target, __m512i signs) {
    __mmask32 negmask = _mm512_movepi16_mask(signs);
      // vpsubw target{negmask}, 0, target  merge masking to only modify elements that need negating
    __m512i neg = _mm512_mask_sub_epi16(target, negmask, _mm512_setzero_si512(), target);

    __mmask32 nonzeromask = _mm512_test_epi16_mask(signs,signs);  // per-element non-zero?
    return  _mm512_maskz_mov_epi16(nonzeromask, neg);        // zero elements where signs was zero
}
Run Code Online (Sandbox Code Playgroud)

可能地,编译器可以这种零掩蔽折叠vmovdqu16禀成合并掩蔽为add/ or/ xor或零掩码乘/ and。但是,自己动手做可能是个好主意。