Мне пришлось вычислять вес Хэмминга для довольно быстрого непрерывного потока 64-битных данных, и с помощью инструкции сборки popcnt
выдает мне исключение из моего Intel Core i7-4650U.
Я проверил свой библейский хакерский восторг и просмотрел веб-страницы для всех видов алгоритмов (это куча там, так как они начали решать эту "проблему" при рождении вычислений).
Я провел выходные, играя с некоторыми своими идеями и придумал эти алгоритмы, где я почти на скорости могу перемещать данные в CPU и из него.
//64-bit popcnt using BMI2
_popcnt_bmi2:
mov (%rdi),%r11
pext %r11,%r11,%r11
not %r11
tzcnt %r11,%r11
mov %r11,(%rdx)
add $8h,%rdi
add $8h,%rdx
dec %rsi
jnz _popcnt_bmi2
ret
В приведенном выше коде я использую pext
(BMI2), где входящие данные используют себя как маску. Затем все существующие биты будут сжиматься, начиная с младшего значащего бита в реестре результатов (сам снова). Затем мне нужно вычислить количество свернутых битов, чтобы я инвертировал все биты, а затем использовал tzcnt
для подсчета числа, теперь нулей. Я думал, что это была неплохая идея.
Затем я также попробовал подход AVX2:
//64-bit popcnt using AVX2
_popcnt_avx2:
vmovdqa (%rcx),%ymm2
add $20h,%rcx
vmovdqa (%rcx),%ymm3
add $20h,%rcx
vmovdqa (%rcx),%ymm4
popcnt_avx2_loop:
vmovdqa (%rdi),%ymm0
vpand %ymm0, %ymm2, %ymm1
vpandn %ymm0, %ymm2, %ymm0
vpsrld $4h,%ymm0, %ymm0
vpshufb %ymm1, %ymm3, %ymm1
vpshufb %ymm0, %ymm3, %ymm0
vpaddb %ymm1,%ymm0,%ymm0 //popcnt (8-bits)
vpsadbw %ymm0,%ymm4,%ymm0 //popcnt (64-bits)
vmovdqa %ymm0,(%rdx)
add $20h,%rdi
add $20h,%rdx
dec %rsi
jnz popcnt_avx2_loop
В случае с AVX2 я прочитал 32 байта, затем замаскиваю полубайты (ymm2
), затем я использую ymm3
в качестве таблицы поиска для бит, подсчитывающих куски. Затем я добавляю результаты к 8-битным, а затем я использую суперконденсированный vpsadbw
, чтобы добавить 8 байтов в 64-битное значение (ymm4
= 0).
У кого-то есть что-то более быстрое по сравнению с их sleves?
Edit:
Ошибка popcnt
произошла из-за ошибки, которую я сделал в моем коде, эта функция работает с моим Intel Core i7-4650U. Пожалуйста, смотрите мой пост ниже, показывая результаты скамейки.