Мой первоначальный подход к этому был похож на подход @Jason R, потому что так работают «обычные» операции, но большинство из этих операций заботятся только о старшем бите, игнорируя все остальные биты. Как только я понял это, серия функций стала наиболее разумной. Вам нужно будет включить -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))
, но я включаю другие для справки / сравнения.
Обратите внимание, что каждый байт / слово / ... будет состоять либо из единиц, либо из нулей в соответствии с маской (а не только старшим битом). Это также может быть полезно для выполнения векторизованных битовых операций (& 'с другим вектором, например, для обнуления ненужных байтов / слов).
Еще одно замечание: каждый _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;
}
Остальные инструкции аналогичны.
person
technosaurus
schedule
27.08.2015
_mm256_mask_blend_epi8(__mmask32 k, __m256i a, __m256i b)
, используя целое число в качестве маски - person technosaurus   schedule 29.08.2015vpsllvd
, чтобы поместить разные биты маски в бит знака каждого элемента. Это отлично подходит для элемента размером 32b, но не для 8b. - person Peter Cordes   schedule 08.04.2016