Самый быстрый 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. Пожалуйста, смотрите мой пост ниже, отображающий результаты тестирования.

Ответы на вопрос(2)

Ваш ответ на вопрос