我的初始方法与 @Jason R's 相似,因为这是“正常”操作的方式,但是大多数这些操作只关心高位 - 忽略所有其他位。一旦我意识到这一点,_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或全部为0(不仅仅是最高位)。这对于执行矢量化的位操作(例如和另一个向量进行'&'运算以消除不需要的字节/字)也很有用。
另一个注意点:每个_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;
}
其他指令类似。
_mm256_mask_blend_epi8(__mmask32 k, __m256i a, __m256i b)
函数,将整数作为掩码。 - technosaurusvpsllvd
变量移位将掩码的不同位放入每个元素的符号位中。这对于元素大小为32b非常有用,但对于8b则不是很好。 - Peter Cordes