我最初的方法类似于@Jason R,因为这就是“正常”操作的工作方式,但是这些操作中的大多数只关心高位——忽略所有其他位。一旦我意识到这一点,这一_mm*_maskz_broadcast*_epi*(mask,__m128i)
系列的功能就最有意义了。您需要启用 -mavx512vl 和 -mavx512bw (gcc)
根据掩码获取每个字节集的最高位的向量:
/* convert 16 bit mask to __m128i control byte mask */
_mm_maskz_broadcastb_epi8((__mmask16)mask,_mm_set1_epi32(~0))
/* convert 32 bit mask to __m256i control byte mask */
_mm256_maskz_broadcastb_epi8((__mmask32)mask,_mm_set1_epi32(~0))
/* convert 64 bit mask to __m512i control byte mask */
_mm512_maskz_broadcastb_epi8((__mmask64)mask,_mm_set1_epi32(~0))
根据掩码获取每个单词集的最高位的向量:
/* convert 8 bit mask to __m128i control word mask */
_mm_maskz_broadcastw_epi16((__mmask8)mask,_mm_set1_epi32(~0))
/* convert 16 bit mask to __m256i control word mask */
_mm256_maskz_broadcastw_epi16((__mmask16)mask,_mm_set1_epi32(~0))
/* convert 32 bit mask to __m512i control word mask */
_mm512_maskz_broadcastw_epi16((__mmask32)mask,_mm_set1_epi32(~0))
根据掩码获取每个双字集的最高位的向量:
/* convert 8 bit mask to __m256i control mask */
_mm256_maskz_broadcastd_epi32((__mmask8)mask,_mm_set1_epi32(~0))
/* convert 16 bit mask to __m512i control mask */
_mm512_maskz_broadcastd_epi32((__mmask16)mask,_mm_set1_epi32(~0))
根据掩码获得每个四字组最高位的向量:
/* convert 8 bit mask to __m512i control mask */
_mm512_maskz_broadcastq_epi64((__mmask8)mask,_mm_set1_epi32(~0))
这个问题的一个具体问题是:_mm256_maskz_broadcastb_epi8((__mmask32)mask,_mm_set1_epi32(~0))
但我将其他问题包括在内以供参考/比较。
请注意,根据掩码(不仅仅是最高位),每个字节/字/...将全为 1 或全为零。这对于执行矢量化位操作也很有用(例如,与另一个矢量进行 &' 以将不需要的字节/字清零)。
另一个注意事项:每个都_mm_set1_epi32(~0)
可以/应该转换为一个常量(手动或由编译器),因此它应该编译为一个相当快速的操作,尽管它在测试中可能比在现实生活中稍微快一些,因为常量可能会保留在寄存器中。然后将这些转换为VPMOVM2{b,w,d,q} 指令
编辑:如果您的编译器不支持 AVX512,则内联汇编版本应如下所示:
inline __m256i dmask2epi8(__mmask32 mask){
__m256i ret;
__asm("vpmovm2b %1, %0":"=x"(ret):"k"(mask):);
return ret;
}
其他指令类似。