HexToDword

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

  1. bogrus

    bogrus Active Member

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




    Доделать может не проблема, но как ты предлагаешь обрабатывать ситуацию при передаче указателя на строку 0x00401FFE db "1",0 (страницы 0x00402000 нет), двордом тут не прочитаешь ...







    Них... себе ~190 на атлоне с 3-мя то alu! против ~16\~32 с 2-мя на пне3\4
     
  2. leo

    leo Active Member

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

    Не пугайся, это видимо на 8 проходов: ~190/8 = 24 ;)
     
  3. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Вариант с табличкой. 40 тиков на одной и той же строке, и порядка 60 для 4 приведенных. Ввиду большой латентности и большого размера таблички (232 байта), алгоритм пригоден только для массовой конвертации строк. Тестирование проводил на iCel4 @2400.
    Код (Text):
    1.  
    2. <font face="fixedsys]
    3. <font size=1>
    4.     char* hdig [4] =
    5.     { "12340AB",
    6.       "ADD50503",
    7.       "Ed1Ad114",
    8.       "abcdef1" };
    9.  
    10.     // 0xF, 0x4F
    11.     DWORD hash [0x3A];
    12.     memset (hash, 0, sizeof (hash));
    13.     for (int x = 0x31; x < 0x39; x ++) hash [x] = x & 0x0F;
    14.     for (int x = 0x41; x < 0x47; x ++) hash [x & 0x3F] = (x & 0x0F) + 0x09;
    15.     for (int x = 0x61; x < 0x67; x ++) hash [x & 0x3F] = (x & 0x0F) + 0x09;
    16.    
    17.     for (int a = 10000000; a--;)
    18.     _asm
    19.     {
    20.         push        eax
    21.         push        ebx
    22.         push        ecx
    23.         push        edx
    24.         // push     esi
    25.         push        edi  
    26.         mov         eax, [a]
    27.         and         eax, 3     
    28.         mov         edi, [hdig + eax * 4]      
    29.         xor         eax, eax
    30.         xor         ecx, ecx       
    31.         xor         edx, edx
    32. xloop:  
    33.         shl         eax, 8
    34.         movzx                   ebx, byte ptr [edi]        
    35.                 and         ebx, 03Fh      
    36.         or          eax, dword ptr [hash + ebx * 4]    
    37.         cmp         byte ptr [edi + 1], 30h
    38.         jb          lbreak
    39.         ;; 2               
    40.         shl         edx, 8
    41.         movzx                   ebx, byte ptr [edi + 1]
    42.                 and         ebx, 03Fh
    43.         or          edx, dword ptr [hash + ebx * 4]
    44.         cmp         byte ptr [edi + 2], 30h
    45.         jb          lbreak
    46.         ;; 3
    47.         shl         eax, 8
    48.         movzx                   ebx, byte ptr [edi + 2]
    49.                 and         ebx, 03Fh
    50.         or          eax, dword ptr [hash + ebx * 4]
    51.         cmp         byte ptr [edi + 3], 30h
    52.         jb          lbreak
    53.         ;; 4
    54.         shl         edx, 8
    55.         movzx                   ebx, byte ptr [edi + 3]
    56.                 and         ebx, 03Fh
    57.         add         edi, 4
    58.         or          edx, dword ptr [hash + ebx * 4]    
    59.         cmp         byte ptr [edi], 30h
    60.         jnb         xloop
    61.         shl         eax, 4
    62.         jmp         complete
    63. lbreak:
    64.         shl         edx, 4     
    65. complete:
    66.         or          eax, edx
    67.         pop         edi
    68.         //pop           esi
    69.         pop         edx
    70.         pop         ecx
    71.         pop         ebx
    72.         pop         eax
    73.     }
    74. </font><!--size--></font><!--face-->
    75.  
     
  4. cresta

    cresta Active Member

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

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

    Ещё и wintest'ом проверил - цифры другие, пропорции те же.



    bogrus

    Это на 8 строк 190 :) А вот быстро положить строку на маску нулей не получается :dntknw: С генерацией строки таким способом получаются примерно те же цифры, что и для других алгоритмов.



    alpet

    А почему табличка 232, а не 220 байт? Если таблицу не двордов, а байт сделать, не пробовал?
     
  5. alpet

    alpet Александр

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

    1. Максимальное значение с учетом маскировки - 39h, соответственно табличка - 3Ah * 4 = 0E8h, что вроде равно 232. Впрочем если маскировать по 1Fh (блин, как я сразу не догадался - символы \x30..\x39 попадают в диапазон 10h..19h, а буквы соответственно в 01h..06h), то табличка получается небольшой - 1Ah * 4 = 68h байт, или до 4-х кэш-линеек по 32 байта. Скорость кстати возросла до 48 тиков для меняющихся строк.



    2. Пробовал - практически особой разницы не заметил (не намного медленнее), но имхо не стоит - в таких делах конфликт банков обойдется дороже чем память, плюс еще может пенальти быть по partial stall.
     
  6. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    По типу buliaNaza, но без sbb (~60 на п3)
    Код (Text):
    1.             mov     esi,buffer
    2. ;===================================
    3. h2d:        xor     eax,eax
    4.             xor     ecx,ecx
    5. @@:         movzx   edx,byte[esi]
    6.             shl     eax,4
    7.             and     ecx,0x0F
    8.             shr     edx,6
    9.             add     eax,ecx
    10.             movzx   ecx,byte[esi]
    11.             lea     edx,[edx*8+edx]
    12.             add     ecx,edx
    13.             lea     esi,[esi+1]
    14.             jnz     @b
    15. ;===================================
     
  7. cresta

    cresta Active Member

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

    Не работает. Результат выдает неверный. И очень долго - более 2000 тактов на 8 строк.





    Вот вариант с таблицей: таблица маленькая - 55 байт, и процедура тоже маленькая.


    Код (Text):
    1.     h_tbl   db  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0
    2.             db  0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0
    3.             db  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    4.             db  0,10,11,12,13,14,15
    5.  
    6.     mov     edx,[esp+4]
    7.     xor     eax,eax
    8.     xor     ecx,ecx
    9.     jmp     _st
    10. _add:
    11.     movzx   ecx,byte ptr[offset h_tbl+ecx]
    12.     shl     eax,4
    13.     inc     edx
    14.     add     eax,ecx    
    15. _st:movzx   ecx,byte ptr[edx]
    16.     sub     ecx,30h
    17.     jns     _add
    18.     retn    4




    376 тиков на 8 строк. Ограничений по регистру букв и длине строки нет.
     
  8. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta На какой это строке не работает? На 3-пне у него скорость точно такая, как в твоем с таблицей
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    На том наборе из 8 строк по 7 символов, что предлагал leo

    На строку "3ccD24c" выдаёт 1521179033, хотя остальные 3 процедуры выдают 63754828. И время 2780 тиков. Чёто там поломаное. Делаю так:


    Код (Text):
    1.             push    esi
    2.             mov     esi,[esp+4]
    3.             xor     eax,eax
    4.             xor     ecx,ecx
    5. @@:         movzx   edx,byte ptr[esi]
    6.             shl     eax,4
    7.             and     ecx,0Fh
    8.             shr     edx,6
    9.             add     eax,ecx
    10.             movzx   ecx,byte ptr[esi]
    11.             lea     edx,[edx*8+edx]
    12.             add     ecx,edx
    13.             lea     esi,[esi+1]
    14.             jnz     @b
    15.             pop     esi
    16.             retn    4
    17.             ;----------------------
    18.             push    offset h_str1
    19.             call    h2d
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Вот вариант с предыдущей таблицей (55 байт) - ещё короче и ещё быстрее:


    Код (Text):
    1.     mov     edx,[esp+4]
    2.     xor     eax,eax
    3.     xor     ecx,ecx
    4.     jmp     _st
    5. _add:
    6.     shl     eax,4
    7.     inc     edx
    8.     or      al,byte ptr[offset h_tbl+ecx]
    9. _st:movzx   ecx,byte ptr[edx]
    10.     sub     ecx,30h
    11.     jns     _add
    12.     retn    4




    На предложенном leo наборе из 8 строк 360 тиков (в среднем 45 тиков).



    P.S.

    Если воспользоваться обстоятельством, что jmp _st - безусловный, можно после него воткнуть align 16 и выравнять метку _add. Так ещё быстрее - 340 тиков.
     
  11. bogrus

    bogrus Active Member

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




    Я б и сам удивился, если вместо ascii2hex получилось ascii2dec :), ты поставил "mov esi,[esp+4]" (надо 8)
     
  12. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Народ, хватит esi/edi/ebx использовать ! Такие оплошности из-за этого :))



    Еще вариант с табличкой + регистр ebx:


    Код (Text):
    1.      mov     edx,[esp+4]
    2.      push    ebx
    3.      xor     eax,eax
    4.      jmp     _st
    5.  
    6. _add:shl     eax,4
    7.      add     edx,2
    8.      or      al,byte ptr[offset h_tbl+ecx]
    9.      shl     eax,4
    10.      or      al,byte ptr[offset h_tbl+ebx]
    11. _st: movzx   ecx,byte ptr[edx]
    12.      sub     ecx,30h
    13.      movzx   ebx,byte ptr[edx+1]
    14.      js      _end
    15.      sub     ebx,30h
    16.      jns     _add
    17.      shl     eax,4
    18.      or      al,byte ptr[offset h_tbl+ecx]
    19. _end:pop     ebx
    20.      retn    4




    266 тиков на 8 проходов.



    P.S.

    Забыл: h2d заработала :) 406 тиков.
     
  13. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Еще один табличный вариант. Порядка 45 тиков / цикл, при тесте в 50 млн. циклов, в случае с одной строкой - 30 тиков. Процессор - iCel@2400. Положительный момент - нет сдвигов, что должно нравится интеловским процессорам (моему домашнему Athlon вроде без разницы).


    Код (Text):
    1.  
    2. <font face="fixedsys]
    3. <font size=1>
    4.     DWORD hash [0x1A];
    5.         char* hdig [4] = { "12340AB", "ADD50503", "Ed1Ad114", "abcdef1" };
    6.     const int loops = 50000000;
    7.     memset (hash, 0, sizeof (hash));
    8.     for (int x = 0x30; x < 0x3A; x ++) hash [x & 0x1F] = (x & 0x0F);
    9.     for (int x = 0x61; x < 0x67; x ++) hash [x & 0x1F] = (x & 0x0F) + 0x09;
    10.    
    11.     SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
    12.     DWORD ticks = 0;               
    13.     nticks = GetTickCount ();  
    14.     __int64 ntc = rdc (); // rdtsc
    15.     _asm
    16.     {
    17.         push        eax
    18.         push        ebx
    19.         mov         edi, 0
    20.         xor         ebx, ebx
    21.         mov         esi, loops ;; loops = 50 millions.
    22.         neg         esi    
    23. bbtest:        
    24.         push        eax
    25.             mov         edx, [hdig + edi * 4]
    26.         add         edi, 1     
    27.         xor         eax, eax                       
    28.         and         edi, 3
    29. lstart:
    30.         movzx       ebx, word ptr [edx + 0]
    31.         and         ebx, 1Fh       
    32.         jz          lbreak
    33.         movzx       ecx, byte ptr [edx + 1]    
    34.         add         eax, eax               
    35.         // second half-byte
    36.         mov         ebx, dword ptr [hash + ebx * 4]            
    37.         add         edx, 2
    38.         lea         eax, [ebx + eax * 8]
    39.         and         ecx, 1Fh
    40.         jz          lbreak
    41.         add         eax, eax
    42.             mov         ecx, dword ptr [hash + ecx * 4]        
    43.         lea         eax, [ecx + eax * 8]       
    44.         jmp         lstart
    45. lbreak:
    46.         pop         eax
    47.         add         esi, 1
    48.         jnz         bbtest  
    49.         pop         ebx    
    50.         pop         eax
    51.     }
    52.     ntc = rdc () - ntc;
    53. </font><!--size--></font><!--face-->
    54.  




    <font face="arial]<font size=1>

    На байтовой табличке - скорость падает до 50-55 тиков/цикл, как впрочем и при смешивании кода с 8-битными / 32-битными регистрами.

    </font><!--size-->

    </font><!--face-->
     
  14. cresta

    cresta Active Member

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

    Всё бы хорошо, только вот код не асмовый :dntknw: Табличка как выглядит? .
     
  15. alpet

    alpet Александр

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

    [01h..06h] = 10..15

    [11h..19h] = 0..9



    hash dd 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Может зря отказался от расширения таблицы до диапазона маленьких букв? Наверное было бы быстрее. Сейчас показывает 354 тика на 8 строк.

    И lea разве быстрее получится, чем shl?



    Кстати, на байтовой таблице не очень много и теряется: 370 тиков (46 на одну строку).





    P.S.

    Попробовал для своего последнего варианта двордовую таблицу - с ней хуже, чем с байтовой :dntknw: Стало 280 тиков.

    Видимо переходы в цикле стали по неоптимальным адресам.
     
  17. alpet

    alpet Александр

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

    1. Табличка и так жирная, а без маскировки как ее юзать.

    2. Дык я и не пытался ее оптимизировать, надо добраться до Атлона, который к сожалению пока недееспособен. Просто направление - способ показал. С другой стороны твой последний алгоритм дает в среднем 50 тиков, может у нас оценки по разному выставляются. У меня вычисляется через кол-во тактов, за очень большое количество проходов (50 млн.), по 4 строкам.

    3. У меня получалось быстрее во всяком случае - на Celeron сдвиг на 4 с сложением так быстрее получается.

    4. Но и не много обретается - 1Ah * 4 = 104 байта не так уж и много для хэш-таблички, а вот конфликт банков в этом алгоритме зависит от данных.
     
  18. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Я своей программой меряю время исполнения. Вроде дееспособная, щас засомневался, проверил в wintest'е by A.Fog - 272 тика. Разница есть с 266, почему - хрен знает, но примерно совпадают показания.



    Надо еще с одной голой процедурой сделать exe, посмотреть.
     
  19. cresta

    cresta Active Member

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







    Я считаю через rdtsc с поправкой на время, необходимое для опроса самого счетчика.

    Строк - 8 штук, те, что приводил leo, за один замер поочередно преобразуются эти восемь строк по одному разу и тест заканчивается.



    С другой стороны твой последний алгоритм дает в среднем 50 тиков, может у нас оценки по разному выставляются.



    Не удивлюсь, если ты меряешь приведенную мною процедуру в виде ассемблерной вставки в сях :))).

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



    Для примера: вот твоя процедура, вернее то, что от неё осталось. С твоего позволения я её слегка отрихтовал, не меняя логику работы.


    Код (Text):
    1. alpet_proc:
    2.         mov     edx,[esp+4]
    3.         push    ebx
    4.         xor     eax,eax
    5. align 16
    6. lstart:
    7.         movzx   ebx, word ptr [edx + 0]
    8.         movzx   ecx, byte ptr [edx + 1]
    9.         and     ebx, 1Fh
    10.         jz      lbreak
    11.         add     eax, eax
    12.         mov     ebx, dword ptr [offset hash + ebx * 4]
    13.         add     edx, 2
    14.         lea     eax, [ebx + eax * 8]
    15.         and     ecx, 1Fh
    16.         jz      lbreak
    17.         add     eax, eax
    18.         mov     ecx, dword ptr [offset hash + ecx * 4]
    19.         lea     eax, [ecx + eax * 8]
    20.         jmp     lstart
    21. lbreak:
    22.         pop     ebx
    23.         retn    4




    В таком виде она выполняется у меня за 294 тика, а было первоначально 354. 60 тиков ушло вместе с мусором ненужных инструкций:) Тут и сейчас есть, что поковырять. Например, цикл длинный. 14 инструкций. На одну инструкцию уходит с учетом всяких пенальти 2,205 тика.

    У меня на одну инструкцию уходит больше времени - 2,420 тика. Только цикл у меня из 11 инструкций, поэтому выполняются в сумме более медленные инструкции быстрее: 26,62 на цикл против 30,87. Это объясняет почему быстрее процедура в целом.

    Естественно, на другом проце и цифры другие, какие не скажу, у меня только Атлон.
     
  20. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Наверное твой алгоритм медленно выполняется у меня из-за того что код в вставке не выравнивается, да и сдвиги у Атлона побыстрее работают. Соберу в скором времени свой Атлон и буду смотреть на нем, без CodeAnalyst здесь сложно. Можно получить весь код теста целиком для FASM?