CRC32 - кто может быстрее?

Тема в разделе "WASM.A&O", создана пользователем Atlantic, 22 май 2007.

  1. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    В аттаче код для вычисления CRC32 (не ругайте за Дельфи, я его использую как оболочку для АСМ-кода) - тестовая прога. На Атлонах скорость - 5 тактов/байт, на P4 - 6 тактов/байт. Кто-нибудь может еще соптимизировать этот код? Просто в сети не встречал более быстрых реализаций (да и равных по скорости тоже).
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Atlantic
    1) По скорости для атлонов и P4Е это предел (2 такта на xor\shr + загрузка байта из кэша = 3 такта на атлонах и 4 на P4E). А вот для исключения partial register stall в P6 лучше предварительно очистить ebx,ecx,edx и вместо movzx использовать загрузку mov bl и т.д. (в AMD64 movzx тоже требует доп.такта, но в данном сл.это роли не играет)
    2) Проверять лень, но похоже, что разворот цикла тут ничего не дает. Попробуй без разворота, скорее всего получатся те же 5-6 тиков
    Код (Text):
    1.   xor edx,edx
    2. @0:
    3.   mov dl,[esi+edi]
    4.   xor dl,al
    5.   shr eax,8
    6.   xor eax,dword [CRCTable+edx*4]
    7.   add edi,1
    8.   jnz @0
     
  3. RElf

    RElf New Member

    Публикаций:
    0
    Регистрация:
    25 дек 2004
    Сообщения:
    159
  4. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    leo
    Приятно слышать :)

    Цикл без разворота работает медленнее (на Атлонах - точно). Разворот в два раза дал ускорение (на сколько точно - не помню, давно это было), на разворот в 4 раза не хватило регистров, пришлось извращаться с разворотом в 3 раза.

    Про partial register stall - вроде бы команда xor eax,dword ptr [CRCTable+ebx*4] все равно его вызовет, так как считывается ebx целиком.

    RElf
    Таблица для обработки двух байтов за раз будет занимать 65536*4=256 килобайт, так что она не влезет в кэш L1, и, учитывая случайный характер обращений к ней, тормоза будут ужасные (все это тоже пробовал - скорость хуже, чем у таблицы 256*4).
     
  5. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Кстати, нашел свой старый код, который я писал специально под P6 (выравнивание важно):
    Код (Text):
    1. function ComputeCRC(var TestBlock;NBytes:Cardinal):Cardinal;assembler;register;
    2. asm
    3.   push ebx// align 3Ch mod 100h
    4.   push esi
    5.   db 8Dh,8Ch,2,0,0,0,0//lea ecx,[eax+edx+0]
    6.   xor eax,eax
    7.   sub eax,1
    8.   neg edx
    9.   @0:
    10.   movzx esi,byte ptr [ecx+edx]
    11.   movzx ebx,al
    12.   shr eax,8
    13.   xor ebx,esi
    14.   mov esi,dword ptr [CRCTable+ebx*4]
    15.   xor eax,esi
    16.   inc edx
    17.   jnz @0
    18.   pop esi
    19.   pop ebx
    20.   xor eax,-1
    21. end;
    6 тактов на P6, Атлонах и P4 Northwood, 7 тактов на P4 Prescott
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Atlantic
    Придется проверить на досуге ;)

    Если ebx был предварительно очищен, то нет, т.к. в P6 xor\sub r,r это спец.команды, после которых старшие разряды регистра считаются ощищенными и текущие темп-образы bl и ebx совпадают, поэтому комбинировать bl с ebx не нужно и никакого stall нет
     
  7. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Проверил на P4E - разницы между развернутым и неразвернутым циклом нет. Вечером проверю на K8.

    Ну вот, добрался до своего домашнего Athlon 64 - без разворота цикл работает со скоростью 6 тактов на байт вместо пяти. Так что разворот все-таки нужен.