BiN2HeX

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

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Не знаю, визуально вроде разница только bswap vs shr, второе должно быть быстрее - на деле наоборот.



    Тут мысль одна появилась - не по полбайта обрабатывать, а побайтно, но к сожалению удалось только для одного байта так сделать - в регистре увы, только 32 разряда. Было бы 33 - можно было бы 2 раза такое провернуть. Для первого и последнего полубайта:


    Код (Text):
    1.             mov     ecx,87654321h
    2. ;-------------------------------------------------------
    3.             mov     eax,ecx
    4.             mov     ebx,2040810h
    5.             and     eax,11110000000000000000000000001111b
    6.             mul     ebx
    7.             and     edx,00000001000000010000000100000001b
    8.             and     eax,00010000000100000001000000010000b
    9.             add     edx,30303030h
    10.             shr     eax,4
    11.             bswap   edx
    12.             add     eax,30303030h
    13.             mov     [edi],edx
    14.             bswap   eax
    15.             mov     [edi+28],eax




    С таким фокусом удалось из 4-х десятков выскочить - 36 тиков. Остальные тетрады бит по прежнему сделаны.
     
  2. leo

    leo Active Member

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

    > "Тут мысль одна появилась - не по полбайта обрабатывать, а побайтно"



    Гениально !

    И умножение на 08040201h позволяет это сделать:
    Код (Text):
    1. ;в edx - байт
    2. imul edx,08040201h
    3. mov ecx,edx
    4. shr edx,3 ;биты 4..1 в нужном порядке
    5. shr ecx,7 ;биты 8..5 в нужном порядке
    6. ... + специи по вкусу ;)
    PS: и все-таки твой Атлон - капризный ;) Может он любит в перестановки играть и замены or на add :))
     
  3. leo

    leo Active Member

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

    Может симпатичный цикл сделать на 4 байта:
    Код (Text):
    1.  
    2.     ;push edi, push ebx
    3.     mov edi,bin_str
    4.     mov eax,87654321h
    5.     ;=================
    6.     mov ecx,24
    7. align 16 ;на 4 прохода может и align то не нужен
    8. @@:
    9.     mov edx,eax
    10.     and edx,0FFh
    11.     imul edx,08040201h
    12.     shr eax,8
    13.     and edx,88888888h
    14.     mov ebx,edx
    15.     shr edx,3
    16.     shr ebx,7
    17.     or edx,30303030h
    18.     mov [edi+ecx+4],edx
    19.     or ebx,30303030h
    20.     mov [edi+ecx],ebx
    21.     sub ecx,8
    22.     jge @B
    23.     ;pop ebx, pop edi
    24.     ;mov byte [edi+32],0 ;замыкающий нолик не забыть !
    На P4 получается 60-64 тика (для сравнения исходный вариант bogrus - 116 тиков, первый вариант cresta - 76 тиков).



    Кстати, на P4 опять cpuid искажает тики при записи в память, поэтому приведенные результаты - это с CLD. Надо бы поэкспериментировать да с kaspersky подискутировать на эту тему, а то он опять пропал ;)
     
  4. cresta

    cresta Active Member

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

    Подкалываешь :) Похоже ты не понял. Я говорю не о стоящих подряд битах. Умножение на 204081h "размазывает" младший полубайт равномерно по всему дворду с периодичностью 8 бит, осталось только and и add/or.


    Код (Text):
    1. mov eax,87654321h      ;[b]1000[/b]0111011001010100001100100001
    2. shr eax,28             ;0000000000000000000000000000[b]1000[/b]
    3. imul eax,204081h       ;0000000[b]1[/b]0000001[b]0[/b]0000010[b]0[/b]0000100[b]0[/b]
    4. and eax,01010101h      ;0000000[b]1[/b]0000000[b]0[/b]0000000[b]0[/b]0000000[b]0[/b]
    5. add eax,30303030h      ;31303030h






    А эта штука (08040201h) выдаёт биты в беспорядке, никакой периодичности ни для старших, ни для младших тут не видно. Просто напрасно выполненный код.


    Код (Text):
    1. mov edx,87654321h      ;10000111 01100101 01000011 00100001
    2. imul edx,08040201h     ;01100110 01101111 10000101 00100001
    3. mov ecx,edx            ;01100110 01101111 10000101 00100001
    4. shr edx,3              ;00001100 11001101 11110000 10100100
    5. shr ecx,7              ;00000000 11001100 11011111 00001010




    Заменой множителя с 204081h на 2040810h я "размазываю" не полубайт, а байт, на пару регистров edx/eax: в edx старшая тетрада, в eax младшая. Биты, которые будут преобразованы, стоят не подряд, а на позициях 31-28 и 3-0.


    Код (Text):
    1. mov     ecx,87654321h  ;10000111 01100101 01000011 00100001
    2. mov     eax,ecx        ;10000111 01100101 01000011 00100001
    3. mov     ebx,2040810h   ;для mul вместо imul
    4. and     eax,0F000000F  ;[b]1000[/b]0000 00000000 00000000 0000[b]0001[/b]
    5. mul     ebx            ;в edx - биты 31-28, в eax - биты 3-0
    6.                        ;в обоих регистрах с периодичностью 8 бит.
    7. and     edx,01010101h  ;0000000[b]1[/b] 0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]0[/b]
    8. and     eax,10101010h  ;000[b]0[/b]0000 000[b]0[/b]0000 000[b]0[/b]0000 000[b]1[/b]0000
    9. shr     eax,4          ;0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]1[/b]
    10. add     edx,30303030h  ;31303030h
    11. add     eax,30303030h  ;30303031h




    Но это получается только для крайних тетрад исходного дворда (31-28 и 3-0). Если расстояние между ними меньше, то младшие биты после умножения частично оказываются в edx (в исходном дворде допустим они начинаются не 3-0, а 7-4). Можно конечно после умножения двинуть вправо eax через флаг переноса, чтобы вернуть старший бит из edx в eax. Это должно позволить обработать таким манером два раза. Т.е. (31-28 и 7-4) и (27-24 и 3-0).







    P.S.

    замена or на add - совершенно идентично (по скорости)



    P.P.S.

    Что-то попытался биты цветом выделить - ерунда получилась :dntknw: Пришлось на bold поменять.
     
  5. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Попытался в целях упаковки воспользоваться коммандой pmovskb (MMX,PIII) и был разочарован - на AMD AthlonXP Throughbred каждая такая коммада награждается штрафом в 10-13 тиков (по сведениям CodeAnalyst - stlf opsize), и производительность в результате у алгоритма получается неважная.
     
  6. leo

    leo Active Member

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

    Возможно я тебя не понял, а ты меня ;)



    А умножение байта на 08040201h раскидывает биты по разным тетрадам с инверсией порядка. Перед умножением в edx ес-но должен быть только байт (8 младших разрядов) и никакого перемешивания тут происходить не может. Пример: умножаем столбиком 08040201 на FF:
    Код (Text):
    1.  
    2.               8        4        2        1
    3. 1         0000[b]1[/b]000000001000000001000000001 <-младший бит
    4. 2        0000100000000[b]1[/b]000000001000000001
    5. 3       0000100000000100000000[b]1[/b]000000001
    6. 4      0000100000000100000000100000000[b]1[/b]
    7. 5     0000[b]1[/b]000000001000000001000000001
    8. 6    0000100000000[b]1[/b]000000001000000001
    9. 7   0000100000000100000000[b]1[/b]000000001
    10. 8  0000100000000100000000100000000[b]1[/b]
    11. result    [b]1[/b]111[b]1[/b]011[b]1[/b]111[b]1[/b]101[b]1[/b]111[b]1[/b]110[b]1[/b]111[b]1[/b]111
    12. and       [b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000 ;<- младший
    13. биты      [b]5[/b]   [b]1[/b]   [b]6[/b]   [b]2[/b]   [b]7[/b]   [b]3[/b]   [b]8[/b]   [b]4[/b]    
    потом SHR-ми и OR-ми разделяем биты\байты 1-2-3-4 и 5-6-7-8

    Ес-но если берем не FF, а другое значение, то там где бит = 0, соответсвующее слагаемое отсутствует и соответсвующий выходной бит = 0.



    PS: Да суть то умножения одна и таже, что у тебя, что у меня. Просто 1) нарастание сдвига от младших к старшим как в 08040201 позволяет получить инверсию, 2) расстояние между битами множителя позволяет уместить 8 бит множимого без перемешивания, и запаса старших битов как раз хватает чтобы получить в старшей тетраде 5-й бит; 3) в твоем случае между битами множителя x81 не достаточно расстояния чтобы уложить нужные 8 бит, поэтому ты придумал другой подход - прихватить edx ;)
     
  7. leo

    leo Active Member

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



    Результаты на PIII:
    Код (Text):
    1. 94     исходный вариант bogrus
    2. 44     первый вариант cresta
    3. 50,40  вариант leo (цикл по 4 байтам)
    4. 42,34  тоже с некоторыми перестановками
    Две цифры - вляние выравнивания (с выравниваем хуже, частично м.б. потому что число проходов мало и эффект мал, а нопы - тики съедают).

    Суть перестановки, улучшающей результат на PIII(на P4 это ничего не дает): парочку mov edx,eax + and edx,0FFh переносим вслед за mov [edi..],edx и дополнительно добавляем ее перед циклом для первого прохода
     
  8. S_T_A_S_

    S_T_A_S_ New Member

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




    Я тоже заметил, что многие vector path команды выполняются "быстрее" чем заявлено в документации за счёт спаривания не некоторых стадиях с direct path командами. В CodeAnalyst это хорошо видно, да и замеры деревенскими способами это подтверждают :)





    leo >




    На athlon эта команда выполняется за один такт :)
     
  9. leo

    leo Active Member

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

    Вот и я думаю, что за 1 такт - быстрее некуда ;)

    Поэтому +4 тика при замене 8 bswap на 8 shr, можно объяснить только "потусторонними" эффектами (декодер, порты, спаривание и т.п.)



    Чего-то мне кажется вы с alpet противоположные вещи говорите ;) Суть то у него правильная, но вот противопоставление "группы однотипных операций" и "среди более быстрых" - вызывает сомнение (если эти быстрые не завясят от медленной).
     
  10. cresta

    cresta Active Member

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

    С разворотом бит разобрался.

    Имхо, на таких величинах уже трудно определить, что быстрее. Разница - единицы. align туда - align сюда и все переворачивается.

    На атлоне

    с умножением на 02040810h - 36

    с умножением на 08040201h - 33

    с табличкой вариант alpet - 32



    Разницы в десятки тиков уже нет.
     
  11. S_T_A_S_

    S_T_A_S_ New Member

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

    Суть в том, что vector path команды тоже иногда паралелятся по не указанным в документации причинам :)
     
  12. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Мне в последнее время сдается также что и CodeAnalyst иногда привирает при анализе эмулируемого кода. Иногда он мне подставляет пенальти bank conflict в коммандах даже близко не работающих с памятью. Блин разобраться бы в API его библиотек (особенно *sim32.dll) и переписать эту программу по нормальному... А вообще меня эта программа потихоньку обучает, до знакомства с ней я плохо представлял как работает суперскалярная архитектура, теперь еще надо с VTune познакомиться.
     
  13. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    В VTune анализа пайпа нет :derisive: А что до корректности результатов эмуляции - я как-то тоже усомнился, проверил rdtsc - всё оказалось верно.