Если у вас эффективный BMI2 pext
(например, Haswell и новее, такой же, как AVX2), тогда используйте обратный ответ @ wim на ваш вопрос о том, чтобы идти в другом направлении ( Как эффективно преобразовать 8-битный растровое изображение в массив целых чисел 0/1 с x86 SIMD ).
unsigned extract8LSB(uint8_t *arr) {
uint64_t bytes;
memcpy(&bytes, arr, 8);
unsigned LSBs = _pext_u64(bytes ,0x0101010101010101);
return LSBs;
}
Этот компилируется так, как вы ожидаете для загрузки qword + инструкции pext
. Компиляторы будут выводить постоянную настройку 0x01...
из цикла после вставки.
pext
/ pdep
эффективны на процессорах Intel, которые их поддерживают (задержка 3 такта / пропускная способность 1с, 1 моп, аналогично умножению). Но они не эффективны на AMD, как задержка 18c и пропускная способность. (https://agner.org/optimize/). Если вам небезразлична AMD, вам обязательно следует использовать ответ pmovmskb
@ harold.
Или, если у вас есть несколько смежных блоков по 8 байт, сделайте их с одним широким вектором и получите 32-битное растровое изображение. Вы можете разделить это, если необходимо, или развернуть цикл, используя 4, чтобы сдвинуть вправо растровое изображение и получить все 4 однобайтовых результата.
Если вы просто сохраняете это в памяти сразу, то вам, вероятно, следовало бы выполнить это извлечение в цикле, который записывал исходные данные, а не в отдельном цикле, так что он все еще будет горячим в кеше. AVX2 _mm256_movemask_epi8
- это один моп (на процессорах Intel) с низкой задержкой, поэтому, если ваши данные не находятся в кэш-памяти L1d, тогда цикл, который только делает это, не будет сохранять занятость его исполнительных блоков, пока в ожидании памяти.