avx512中比较内在指令的不同语义?

Fab*_*bio 3 c++ sse intrinsics avx avx512

使用sse2或avx比较操作返回所有零或全部的位掩码(例如_mm_cmpge_pd返回__m128d.

我找不到avx512的等价物.比较操作似乎只返回短位掩码.语义是否发生了根本变化,或者我遗漏了什么?

Jas*_*n R 5

是的,AVX512的语义有点不同.比较指令将结果返回到掩码寄存器中.这有几个优点:

  • (8)掩码寄存器与[xyz]mm寄存器组完全分开,因此不要将向量寄存器浪费在比较结果上.
  • 几乎整个AVX512指令集都有屏蔽版本,使您可以灵活地使用比较结果.

与传统的SSE/AVX实现相比,它确实需要稍微不同的代码,但这并不算太糟糕.

编辑:如果要模拟旧行为,可以执行以下操作:

// do comparison, store results in mask register
__mmask8 k = _mm512_cmp_pd_mask(...);
// broadcast a mask of all ones to a vector register, then use the mask
// register to zero out the elements that have a mask bit of zero (i.e.
// the corresponding comparison was false)
__m512d k_like_sse = _mm512_maskz_mov_pd(k, 
    (__m512d) _mm512_maskz_set1_epi64(0xFFFFFFFFFFFFFFFFLL));
Run Code Online (Sandbox Code Playgroud)

可能有更好的方法来做到这一点,但我自己使用AVX512相对较新.所有的掩码都可以预先计算并重复使用,因此您实际上只需添加一个额外的掩码移动指令来生成您正在寻找的矢量结果.

编辑2:正如Peter Cordes在下面的评论中所建议的那样,您可以使用它_mm512_movm_epi64()来简化以上内容:

// do comparison, store results in mask register
__mmask8 k = _mm512_cmp_pd_mask(...);
// expand the mask to all-0/1 masks like SSE/AVX comparisons did
__m512d k_like_sse = (__m512d) _mm512_movm_epi64(k);
Run Code Online (Sandbox Code Playgroud)

  • 有一个用于将`k`掩码转换为0/-1向量的AVX512DQ(或用于窄元素的AVX512BW)指令:[`__m512i _mm512_movm_epi64(__ mmask16)```VPMOVM2Q zmm1,k1`](https://github.com/HJLebbink/ASM-哥们/维基/ VPMOVM2B_VPMOVM2W_VPMOVM2D_VPMOVM2Q).使用它代替`maskz_mov_pd`,这样你就不需要一个全1常量.或者更好的方法就是尽可能使用面具. (3认同)