HexToDword

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

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    О выравнивании кода: наверное заметил "неправильное" начало процедуры -

    mov edx,[esp+4]

    push ebx

    а не

    push ebx

    mov edx,[esp+8]

    разницы никакой в логике процедуры, а первый вариант выполняется на 10 тиков быстрее. Точно не знаю, но предположительно из-за того, что сложная инструкция в первом варианте выравнена на 16 (перед процедурой align 16)



    или тут:
    Код (Text):
    1.      xor     eax,eax
    2.      jmp     _st
    3. align 16
    4. _add:or      al,byte ptr[offset hh_tbl+ecx]
    5.      shl     eax,4
    6.      or      al,byte ptr[offset hh_tbl+ebx]
    7. _st: movzx   ecx,byte ptr[edx]
    8.      ......
    9.      jns     _add




    Лучше один раз сделать jmp _st, и за счёт этого выравнять начало цикла на 16, что в конечном итоге сэкономит во много раз больше, чем время на jmp.



    Тест у меня не фасмовый, фасм не понимаю (или не хочу). На масме. Если надо, давай мыло, скину.
     
  2. alpet

    alpet Александр

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

    Давай на alpet<font color="red]&40;</font><!--color-->hotmail.ru. У меня есть только masm32. В принципе он вроде и pdb файлы генерит, что необходимо к сожалению для CodeAnalyst.
     
  3. cresta

    cresta Active Member

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

    alpet Александр

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

    Получил, результаты на Celeron в целом в пользу моего алгоритма: 280 тиков, 344 у тебя, 440 у bogrus, и 558 у buliaNaza. Что интересно у тебя первый тест часто получается быстрее второго - например 556 / 860 тиков, и в любом случае быстрее чем у всех остальных алгоритмов - результат видимо малого размера таблички. Подробный результ лови на мыло.
     
  5. leo

    leo Active Member

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

    > "разницы никакой в логике процедуры, а первый вариант выполняется на 10 тиков быстрее. Точно не знаю, но предположительно из-за того, что ..."



    В высокоуровневой логике разницы нет, а в микрооперациях разница существенная, т.к. push\pop\call\ret неявно изменяют регистр esp. Поэтому mov edx,[esp+4] и push ebx могут выполняться параллельно, а вот push ebx и mov edx,[esp+8] нет, т.к. mov должен ждать изменения esp после push.
     
  6. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Сделал так-же и высокоуровневую функцию преобразования, без таблички на C++. Проверял двумя компиляторами - gcc 3.4.2 и ms cl 14.0. Для первого задал опции оптимизации: "-O3 -s -ffast-math -mwindows". Для другого - следующие:
    Код (Text):
    1.  
    2. /Ox /Og /Ob2 /Oi /Ot /G6 /GA /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /EHsc /ML /GS /Yu"stdafx.h"
    3. /Fp"Release/fscan2.pch" /Fo"Release/" /Fd"Release/vc70.pdb" /W3 /nologo /c /Wp64 /Zi /TP
    4.  


    Итог - результат gcc получился размером 7кб и выполнял преобразование в среднем за 80 тиков (грамотное встраивание inline). Результат ms cl = 44кб и 100 тиков (инлайн не использовался, а при задании __forceinline получилось еще хуже - 114 тиков).

    Исходник в аттаче и бинарник(gcc) в аттаче.



    P.S. При этом попытался воспользоваться встроенным ассемблером, но синтаксис асмовых вставок в gcc похоже придумали инопланетяне - все перевернуто с ног на голову, кроме головной боли ничего короче не добился.

    [​IMG] 371609841__1.zip
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Код (Text):
    1. QWORD inline __stdcall rdc ()
    2. {
    3.      asm ("rdtsc\n" );
    4. }




    Это что за зверь? vc++ 7.1 не понимает этого :dntknw:
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Слушай, а что ты GetTickCount'ом меряешь ? Он же миллисекунды возвращает :)
     
  9. alpet

    alpet Александр

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

    Да - это пример убившего меня вчера GNU Assembler syntax (GAS). Вот например еще код:
    Код (Text):
    1.  
    2. int main(void)
    3. {
    4.   int x = 10, y;
    5.   asm ("movl %1, %%eax;    
    6.        "movl %%eax, %0;"
    7.     :"=r"(y)  /* y is output operand */
    8.     :"r"(x)   /* x is input operand */
    9.     :"%eax"); /* %eax is clobbered register */
    10. }
    11.  


    На сколько я понял в традионном асме это выглядит так:
    Код (Text):
    1.  
    2. push eax ; Сохранить ударенный регистр :))
    3. mov  eax, x ; movl %1, %%eax
    4. mov  y, eax ; movl %%eax, %0
    5. pop  eax
    6.  




    GetTickCount правильно юзается - смотри выражение которое тики получает:
    Код (Text):
    1. [b]
    2. double dspeed = ((double) nTicks / (double)loops) / (1000 / 2.4e9);
    3. Equ:
    4.  ( msec_time_of_test /  cycle_loops ) / (msec_in_sec / cpu_speed ).
    5. [/b]
    6. Взялся GetTickCount использовать, потому что не удалось написать на gcc функцию rdtsc (вернее написал - но она
    7. работает только в неоптимизированной версии).
    8.  
    9. Макрос, предложенный на одном из сайтов, gcc не принял. Видать со стандартами плохо в Linux и каждый стремится свой изобрести :(
    10.  
    11. #define rdtscll(val) \
    12.      __asm__ __volatile__ ("rdtsc" : "=A" (val))
    13.  
     
  10. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Умудрился таки немного разобраться в синтаксисе AT&T asm. Результат в аттаче, выводит два результат - по таймеру и по rdtsc. У меня на машине результат таймера обычно оптимистичнее примерно на тик чем у rdtsc. После введения увеличения приоритета код стал выполнятся быстрее - 72-73 тиков на цикл. Я мельком глянул под Olly на сгенерированный код, и весьма был заинтригован - хорошая в целом работа.

    [​IMG] _1556112236__2.zip
     
  11. cresta

    cresta Active Member

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

    А чего не сделать свой rdc?

    В исходнике, что мылил тебе, есть макросы INIT_CLOCK, STOP_CLOCK, READ_CLOCK, SERIAL. Попробуй их вставь как _asm вставку. Или в виде in line функции.

    Можно конечно и с GetTickCount, но масштаб совсем другой, под каждый проц нужен свой коэффициент вместо (1000 / 2.4e9)
     
  12. alpet

    alpet Александр

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

    Дык уже сделал:
    Код (Text):
    1.  
    2. QWORD inline rdc ()
    3. {
    4.     union { QWORD rr; struct { DWORD r1, r2; }; } mix; 
    5.     asm volatile ("rdtsc\n" : "=a"(mix.r1),"=d"(mix.r2) );    
    6.     return mix.rr; 
    7. }
    8.  


    А если юзать твой - gcc воспротивится, ему Intelовский синтаксис непонятен. Вот для MSVC у меня простая rcd inline функция:
    Код (Text):
    1.  
    2. __forceinline __int64   rdc ()
    3. {
    4.     __asm rdtsc
    5. }
    6.  




    Поправка - в принципе можно заставить работать gcc и с интеловским синтаксисом (как и отладчик gdb), но только в плане отдельных файлов - не вставок.