BiN2HeX

Тема в разделе "WASM.A&O", создана пользователем bogrus, 3 июн 2005.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    leo

    На Атлоне это получается 53 тика



    S_T_A_S_

    А что такое ctc???
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Это cmc :)
     
  3. leo

    leo Active Member

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

    > На Атлоне это получается 53 тика



    Вот видишь, значит Атлон тоже не "любит" shld. У каждого семейства свои прибамбасы.

    Поэтому чтобы не нарваться на проблемы, лучше избегать "тяжелых" инструкций, и поэтому же "туповатые" варианты часто показывают пусть не выдающиеся, но зато и не худшие результаты, приемлемые на всех популярных семействах.



    А вот твой второй вариант выглядит просто рекламной издевкой над "отстойными пеньками" ;)

    Тебе удалось наступить на больные мозоли сразу и PIII и P4. Для PIII это известная проблема c partial register stall - почитай А.Фога, у него все варианты на примерах показаны, когда можно и когда нельзя (не нужно) оперировать раздельно с al и eax. А суть такова: в PIII для результата записи в al отводится отдельный temp-регистр и старшая часть eax в него не копируется, а когда вслед за add al идет shl eax проц начинает страшно материться на "нерадивых программеров" и лихорадочно комбинировать результаты из старого eax и нового al. В P4 интелы устранили эту проблему, но взамен добавили новую (но менее катастрофичную) - операции типа add al,dh со старшим и младшим байтами регистра требуют дополнительной микрооперации сдвига dh под al (в P6 это было реализовано аппаратно). Это то ладно, да вот в первых моделях P4 (< 3) еще и на сдвигах и bswap сэкономили (на блоке MMX_SHIFT реализовали) - сдвиги по 4 такта, bswap около 7. Поэтому shl eax,1 всегда следует заменять на add eax,eax (на P4 даже shl eax,4 может работать медленее чем сложения, но для других семейств это конечно будет проигрыш). Ну а bswap нужно просто избегать, как и shld (14 тактов на P4 моделей < 3).

    Вот такие дела... Ну а элементарные сложения\вычитания\логика везде быстрые, поэтому тупые алгоритмы и рулят с неплохой скоростью на всех процах :)



    PS: А еще P4 страшно не любит частичные установки флагов, например CLC\STC\CMC ~10 тактов, CLD\STD вообще не меряно, про inc и так все знают. Поэтому цепочка cmc+inc+rcl на P4 должна показать выдающиеся результаты ;)

    PPS: да вообще-то "ниче" - всего 196 тиков, как и второй вариант cresta ;) Вывод - пеньки это отстой, особенно если их провоцировать и наступать на больные места :))
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    leo

    Так pentium получается вообще ничего не любит :dntknw: Куда не сунься - везде мозоли :) Это что ж, реально у программера остается пара десятков инструкций, которые не страдают недостатками ?
     
  5. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    С умножением на PIII оптимальный вариант такой ~32 (imul минимум 4 такта * 8 проходов = 32)
    Код (Text):
    1. bin2hex:    lea     edx,[eax+32]
    2.         mov     ecx,-32
    3. align 16
    4. @@:     imul    ebx,[edx+ecx],0x80402010
    5.         sub     ebx,0x10000000 ; или dec eax после shld
    6.         shld    eax,ebx,4
    7.         add     ecx,4
    8.         jnz     @b
    Но другим он тогда не понравится :) хотя у них и частота намного выше, по веремени может одинаково оказатся
     
  6. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Выкинули половину умножений и развернули, плюс ebx освободился, много инструкций можно заменить на другие, например с "shld edx,ecx,8" у меня ~25 (а так ~30 и на P4 ~48)
    Код (Text):
    1. bin2hex:    xor     edx,edx
    2.             mov     ecx,[eax+4*0]
    3.             lea     ecx,[ecx*8]
    4.             add     ecx,ecx
    5.             add     ecx,[eax+4*1]
    6.             sub     ecx,0x33333330
    7.             imul    ecx,0x08040201
    8.             and     ecx,0xFF000000
    9.             add     edx,ecx
    10.             mov     ecx,[eax+4*2]
    11.             lea     ecx,[ecx*8]
    12.             add     ecx,ecx
    13.             add     ecx,[eax+4*3]
    14.             sub     ecx,0x33333330
    15.             imul    ecx,0x08040201
    16.             and     ecx,0xFF000000
    17.             shr     ecx,8
    18.             add     edx,ecx
    19.             mov     ecx,[eax+4*4]
    20.             lea     ecx,[ecx*8]
    21.             add     ecx,ecx
    22.             add     ecx,[eax+4*5]
    23.             sub     ecx,0x33333330
    24.             imul    ecx,0x08040201
    25.             and     ecx,0xFF000000
    26.             shr     ecx,16
    27.             add     edx,ecx
    28.             mov     ecx,[eax+4*6]
    29.             lea     ecx,[ecx*8]
    30.             add     ecx,ecx
    31.             add     ecx,[eax+4*7]
    32.             sub     ecx,0x33333330
    33.             imul    ecx,0x08040201
    34.             and     ecx,0xFF000000
    35.             shr     ecx,24
    36.             lea     eax,[edx+ecx]
     
  7. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    leo >




    Ценой лишнего байта, в моём коде можно вынести cmc за цикл, заменив на not eax. rcl на adc наверное нет смысла менять :)
     
  8. leo

    leo Active Member

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



    К твоему последнему варианту:

    1) lea ecx,[ecx*8] + add ecx,ecx можно заменить на shl ecx,4 т.к. на P4 lea с масштабированием не оптимизирована и все равно выполняется как shl

    2) если все таки обрабатывать с конца строки, то можно сдвигать не ecx, а edx - тогда shr edx,8 частично распараллеливается и на P4 получается чуть быстрее - 44 вместо 48 (сколько реальная прибавка трудно сказать - из-за дискретности м.б. от 1 до 7 )
     
  9. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Если совместить все imul в группу, они будут выполняться примерно за 10-12 тиков, а не за 20 (AMD AthlonXP).

    Вот код примерно на 37 тиков:
    Код (Text):
    1.  
    2.     push        eax
    3.     push        ebx
    4.     push        ecx
    5.     push        edx
    6.     push        esi
    7.     lea         esi, bintext       
    8.  
    9.         mov         eax, [esi + 4 * 0]  // 0x31313131
    10.     mov         ecx, [esi + 4 * 2]
    11.         mov         edx, [esi + 4 * 4]  // m.b. bank conflict
    12.         mov         ebx, [esi + 4 * 6]
    13.  
    14.     shl         eax, 4              // 0x13131310
    15.         shl         ecx, 4
    16.         shl         edx, 4
    17.     shl         ebx, 4     
    18.  
    19.     add         eax, [esi + 4 * 1]  // 0x43434341 (src=0x30303030)
    20.         add         edx, [esi + 4 * 3]
    21.         add         ecx, [esi + 4 * 5]
    22.         add         ebx, [esi + 4 * 7]
    23.  
    24.         sub         eax, 0x33333330     // 0x10101010              
    25.         sub         edx, 0x33333330
    26.     sub         ecx, 0x33333330
    27.     sub         ebx, 0x33333330
    28.  
    29.     imul        eax, 0x08040201    // 8 тетрад - в 8 бит, за 5 тиков      
    30.     imul        ecx, 0x08040201            
    31.         imul        edx, 0x08040201    
    32.     imul        ebx, 0x08040201
    33.  
    34.     and         eax, 0xFF000000
    35.     and         ecx, 0xFF000000    
    36.     and         edx, 0xFF000000            
    37.         // ebx no needs masking
    38.         shr         ecx, 8        
    39.         shr         edx, 16              
    40.         shr         ebx, 24    
    41.  
    42.     add         edx, eax
    43.     add         ebx, ecx
    44.         lea         eax, [edx + ebx]
    45.     pop         esi
    46.     pop         edx
    47.     pop         ecx
    48.     pop         ebx
    49.     pop         eax
    50.  
     
  10. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    В принципе на пеньках рулит переименование регистров, т.е. когда мы пишим в любой РОН, то результату на самом деле назначается каждый раз новый временный регистр (которых более 40), в этих алгоритмаx 4 обработки не зависимы от друг друга и могут выполнятся не дожидаясь предыдущих (перегруппировка мопов), зависимость есть только по формированию результата ("add edx,reg" будет выполнятся в последнюю очередь что с группировкой imul, что без, т.ч. из-за push\pop это будет чуть медленнее, на PIII так точно)



    За другие камни не скажу, а у себя чуть ускорял заменив сдвиг и вычитание этим:
    Код (Text):
    1.             mov     ecx,[eax+4*0]
    2.             add     ecx,ecx
    3.             lea     ecx,[ecx*8-0x33333330]
    4.             add     ecx,[eax+4*1]
    А xor edx,edx на imul edx,ecx,0x08040201

    з.ы. может покрутим теперь в обратную сторону (hex_dword > bin_str32) :), вот тупой вариант:
    Код (Text):
    1. ;=========================================
    2.             mov     eax,0x87654321
    3.             mov     edi,bin_str
    4. ;=========================================
    5. hex2bin:    lea     edi,[edi+32]
    6.             mov     ecx,-32
    7. align       16
    8. @@:         add     eax,eax
    9.             mov     dl,0
    10.             adc     dl,0x30
    11.             mov     byte[edi+ecx],dl
    12.             add     eax,eax
    13.             mov     dl,0
    14.             adc     dl,0x30
    15.             mov     byte[edi+ecx+1],dl
    16.             add     eax,eax
    17.             mov     dl,0
    18.             adc     dl,0x30
    19.             mov     byte[edi+ecx+2],dl
    20.             add     eax,eax
    21.             mov     dl,0
    22.             adc     dl,0x30
    23.             mov     byte[edi+ecx+3],dl
    24.             add     ecx,4
    25.             jnz     @b
    26. ;=========================================
     
  11. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Во всяком случае эмулятор конвеера AthlonXP (CodeAnalyst) очень хорошо показывает, что явной зависимостью лучше не баловаться. Группировка imul дает прирост за счет того что dpi этой инструкции в группе все 2 тика, а не 5 когда она находится среди более быстрых операций. Я сейчас алгоритм оптимизирую - поиск всех вхождений байтовых значений в некоторую область памяти с результатами в виде набора множеств. Там тоже приходится делать упаковку результатов команды pcmpeqb (MMX). Поскольку алгоритмы похожие его в конце-концов и для этой задачи можно будет применить наверное. Хотя и не ясно зачем ее так предельно оптимизировать - гигабайты бинарных текстов что-ли лопатить?
     
  12. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    bogrus

    На Атлоне это 68 тиков (hex2bin).



    Вот вариант, дающий на Атлоне 46 тиков:


    Код (Text):
    1. hex2bin:    mov     edx,eax
    2.             shr     edx,28
    3.             imul    edx,204081h
    4.             and     edx,01010101h
    5.             add     edx,30303030h
    6.             bswap   edx
    7.             mov     [edi],edx
    8.             mov     edx,eax
    9.             shr     edx,24
    10.             and     edx,0Fh
    11.             imul    edx,204081h
    12.             and     edx,01010101h
    13.             add     edx,30303030h
    14.             bswap   edx
    15.             mov     [edi+4],edx
    16.             mov     edx,eax
    17.             shr     edx,20
    18.             and     edx,0Fh
    19.             imul    edx,204081h
    20.             and     edx,01010101h
    21.             add     edx,30303030h
    22.             bswap   edx
    23.             mov     [edi+8],edx
    24.             mov     edx,eax
    25.             shr     edx,16
    26.             and     edx,0Fh
    27.             imul    edx,204081h
    28.             and     edx,01010101h
    29.             add     edx,30303030h
    30.             bswap   edx
    31.             mov     [edi+12],edx
    32.             mov     edx,eax
    33.             shr     edx,12
    34.             and     edx,0Fh
    35.             imul    edx,204081h
    36.             and     edx,01010101h
    37.             add     edx,30303030h
    38.             bswap   edx
    39.             mov     [edi+16],edx
    40.             mov     edx,eax
    41.             shr     edx,8
    42.             and     edx,0Fh
    43.             imul    edx,204081h
    44.             and     edx,01010101h
    45.             add     edx,30303030h
    46.             bswap   edx
    47.             mov     [edi+20],edx
    48.             mov     edx,eax
    49.             shr     edx,4
    50.             and     edx,0Fh
    51.             imul    edx,204081h
    52.             and     edx,01010101h
    53.             add     edx,30303030h
    54.             bswap   edx
    55.             mov     [edi+24],edx
    56.             and     eax,0Fh
    57.             imul    eax,204081h
    58.             and     eax,01010101h
    59.             add     eax,30303030h
    60.             bswap   eax
    61.             mov     [edi+28],eax




    Тут bswap всё портит :dntknw: Без него получается вообще 28 тиков.

    Правда строка задом наперед получается. Надо как-то без bswap'а сделать.



    А пока ждем captain cobalt'a с картинкой :)
     
  13. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    Цель не имеет задачи, просто дело было вечером, делать было нечего (такое редко, но случается), это как в DOOM играть, борьба за такты :)







    Ну может кому-то понадобится и такое, тогда лучше пересмотреть варианты на предмет использования таблицы и держать её в L1



    cresta О, это уже гуд, на PIII ~40 вместо ~96, а я думал на что надо умножить чтоб получить обратное,

    captain cobalt'а можно уже не звать :)
     
  14. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Да вот же, одно число нашёл, чтобы разбросать биты по байтам - 204081h, а сейчас голова пухнет про другое число - может есть такое, чтобы байты разворачивало :)



    P.S.

    Пардон.

    Последний bswap в коде был для edx, естественно, нужно bswap eax. В коде уже исправил.
     
  15. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta Можно bswap (для бит полубайтов) сделать один раз, в самом начале попробуй вставить это, правда у меня особого выиграша не получилось, но на P4\Athlon'е кто знает ...
    Код (Text):
    1.             mov     ecx,eax
    2.             and     eax,0x11111111
    3.             shl     eax,3
    4.             mov     edx,ecx
    5.             and     edx,0x22222222
    6.             add     edx,edx
    7.             or      eax,edx
    8.             mov     edx,ecx
    9.             and     edx,0x44444444
    10.             shr     edx,1
    11.             or      eax,edx
    12.             mov     edx,ecx
    13.             and     edx,0x88888888
    14.             shr     edx,3
    15.             or      eax,edx
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    bogrus, на атлоне это хуже чем bswap - получилось 52 тика. Видимо, атлон меньше нервничает из-за bswap.
     
  17. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Табличное преобразование hex2bin.

    По моим прикидкам около 35 тиков.
    Код (Text):
    1.  
    2.     char* tetrs
    3.          = "0000000100100011010001010110011110001001101010111100110111101111";
    4.    
    5.     _asm
    6.     {
    7.         push        eax
    8.         push        ebx
    9.         push        ecx
    10.         push        edx
    11.         push        esi
    12.         push        edi
    13.         mov         esi, tetrs              // table
    14.         lea         edi, bintext            // result
    15.         mov         eax, 1111000010011011b  // Example (debug)
    16.         mov         edx, eax
    17.         mov         ebx, eax
    18.                 shr         edx, 18h
    19.         shr         ebx, 1Ch
    20.         and         edx, 15
    21.         and         ebx, 15            
    22.         mov         ecx, [esi + ebx * 4]
    23.         mov         [edi + 00h], ecx
    24.         mov         ecx, [esi + edx * 4]
    25.         mov         [edi + 04h], ecx
    26.        
    27.         mov         edx, eax
    28.         mov         ebx, eax
    29.                 shr         edx, 10h
    30.         shr         ebx, 14h
    31.         and         edx, 15
    32.         and         ebx, 15            
    33.         mov         ecx, [esi + ebx * 4]
    34.         mov         [edi + 08h], ecx
    35.         mov         ecx, [esi + edx * 4]
    36.         mov         [edi + 0Ch], ecx
    37.  
    38.         mov         edx, eax
    39.         mov         ebx, eax
    40.                 shr         edx, 08h
    41.         shr         ebx, 0Ch
    42.         and         edx, 15
    43.         and         ebx, 15            
    44.         mov         ecx, [esi + ebx * 4]
    45.         mov         [edi + 10h], ecx
    46.         mov         ecx, [esi + edx * 4]
    47.         mov         [edi + 14h], ecx
    48.  
    49.         mov         edx, eax       
    50.                 shr         eax, 4     
    51.         and         edx, 15
    52.         and         eax, 15            
    53.         mov         ecx, [esi + eax * 4]
    54.         mov         [edi + 18h], ecx
    55.         mov         ecx, [esi + edx * 4]
    56.         mov         [edi + 1Ch], ecx
    57.  
    58.         pop         edi
    59.         pop         esi
    60.         pop         edx
    61.         pop         ecx
    62.         pop         ebx
    63.         pop         eax
    64.     }
    65.  
     
  18. leo

    leo Active Member

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

    > "может есть такое, чтобы байты разворачивало"



    Конечно, запиши в обратном порядке - получишь разворот ;)
    Код (Text):
    1. ;в eax 4 значащих бита
    2. imul eax,08040201h
    3. shr eax,3
    4. and eax,01010101h
    5. or  eax 30303030h
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    leo

    Этот вариант может на Pentium сработает, но на Атлоне это тоже медленее, чем с bswap - 50 тиков против 46.
     
  20. leo

    leo Active Member

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



    А ты еще считаешь пеньки капризными ;)

    Кол-во инструкций одинаково, зависимость по данным одна и та же, так неужели на Атлоне популярная shr медленнее сравнительно редкой bswap ?! Или прибамбасы с декодером как в PIII ? Вопрос ес-но риторический ;)