Мой первоначальный подход к этому был похож на @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))
Чтобы получить вектор с наивысшим битом каждого double word установлено в соответствии с маской:
/* 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))
, но я включаю другие для ссылки / сравнения.
Обратите внимание, что каждый байт / слово / ... будет либо всем один или все нули в соответствии с маской (а не только старший бит). Это также может быть полезно для выполнения векторизованных операций с битами (например, с другим вектором, например, для удаления ненужных байтов / слов).
Другое примечание: каждый _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;
}
Другие инструкции аналогичны.