我最初的方法类似于@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 或全为零。这对于进行向量化位操作也很有用(例如,与另一个向量进行 &'ing 以将不需要的字节/字清零)。
另一个注意事项:每个_mm_set1_epi32(~0) 可以/应该转换为常量(手动或由编译器),因此它应该编译为一个相当快速的操作,尽管它在测试中可能比在现实生活中稍快因为常数可能会保留在寄存器中。然后将这些转换为VPMOVM2{b,w,d,q} instructions
编辑:如果您的编译器不支持 AVX512,则内联汇编版本应如下所示:
inline __m256i dmask2epi8(__mmask32 mask){
__m256i ret;
__asm("vpmovm2b %1, %0":"=x"(ret):"k"(mask):);
return ret;
}
其他说明类似。