Самый быстрый 64-битный подсчет населения (вес Хэмминга)
Мне пришлось рассчитать вес Хэмминга для довольно быстрого непрерывного потока 64-битных данных и использоватьpopcnt
Инструкция по сборке исключает меня из моего Intel Core i7-4650U.
Я проверил восторг моей библии Хакера и отсканировал в Интернете все виды алгоритмов (это куча, так как они начали решать эту «проблему» при рождении компьютеров).
Я провел выходные, играя с некоторыми своими собственными идеями, и придумал эти алгоритмы, где я почти на скорости, я могу перемещать данные в ЦПУ и из него.
//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)
Кто-нибудь получил что-то быстрее в рукавах?
Редактировать:
ПадениеPOPCNT
из-за ошибки, которую я сделал в своем коде, эта функция работает на моем Intel Core i7-4650U. Пожалуйста, смотрите мой пост ниже, отображающий результаты тестирования.