Друзья, насколько Ваши Асм-коды реально эффективны?

Тема в разделе "WASM.HEAP", создана пользователем UbIvItS, 17 июн 2018.

  1. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    я акь-то игрался в плане высокоскоростных кодов на Асме и сравнивал их скорость с аналогичной сишечкой. опосля различных камланий да с бубном сишечку удалось превзойти, но для оного понадобилось..

    1. оптимаза под out-of-order execution.
    2. морф.
    3. использование векторных регистров в качестве скалярных переменных.
    +++
    кстати, тот же морф вполне легко заменить указателями на функции == эффект получается примерно сопоставимый. :)
     
  2. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    Обычно современные компиляторы хорошо оптимизируют код, но иногда и тупят конкретно, ещё можно забыть указать выравнивание структур, и балбес компилятор сам не выравняет. В общем, на асме кодить надо уметь, хотя часто всё зависит от алгоритма. На счёт оптимизации, если быстро, то стараюсь команды тасовать так, чтобы параллельно могли выполнится, более тонкими оптимизациями обычно не замарачиваюсь. И ещё, только на ассемблере можно делать хорошие оптимизации на размер, что что но современные компиляторы на оптимизацию на размер делают хреново. Упорото хреново, не помогает даже использования специальных команд, типа |=0, всё равно нагородит своего.
     
  3. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    Intro, а предпочитаешь инлайн вставки иль отдельный модуль пишешь?
     
  4. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    Если на С/С++, то встроенным ассемблером не пользуюсь, предпочитаю полностью на асме программу переписать, в прочим, я сразу делаю на асме, а уже потом, если надо переписываю на С/С++. Короче, или код на С или на ассемблер. Именно поэтому мне нужен ассемблер типа UASM с возможностью вставлять высокоуровневый код.
    И ещё, интересно, если написать программу на асме, а потом портировать на С/С++, то получается более компактный и вероятно более быстрый код.
    Наверно нужен пример.
    Вот код, вычисляем выражения в строке.
    https://habr.com/post/216449/
    У меня этот код на VS2010 не пошёл.
    Сначало сделал на UASM.
    Код (ASM):
    1. ;=========================================================================
    2. ; Консольное утилита для вычисления выражений
    3. ; Для UASM 2.46.10.0
    4. ; Создан:          9.06.2018 г. 20:30
    5. ; Изменения:       10.06.2018 г. 20:00
    6. ; (c) NanoBot
    7. ;=========================================================================  
    8. __MINIMAL_SIZE__     equ <>     ; оптимизация на минимальный размер!
    9.  
    10. .686
    11. .XMM
    12.  
    13. .model flat, stdcall
    14. option casemap:none
    15. include f:\masm32\include\windows.inc
    16. include f:\masm32\include\user32.inc
    17. include f:\masm32\include\kernel32.inc
    18. include f:\masm32\include\masm32.inc
    19. include f:\masm32\include\msvcrt.inc
    20. include f:\masm32\macros\macros.asm
    21. includelib f:\masm32\lib\user32.lib
    22. includelib f:\masm32\lib\kernel32.lib
    23. includelib f:\masm32\lib\masm32.lib
    24. includelib f:\masm32\lib\msvcrt.lib
    25.  
    26.  
    27. __getmainargs     PROTO C :ptr, :ptr, :ptr, :dword, :ptr
    28. GetStartupInfoA     PROTO stdcall :ptr STARTUPINFOA
    29. main         PROTO C   argc:dword, argv:ptr, environ:ptr
    30.  
    31. ;========================= MACROSES =========================
    32. LABEL_EXPR       equ 1b               ; метка кода
    33. MEM_EXPR       equ 10b               ; память
    34. IMM_EXPR       equ 100b             ; непосредственное выражение
    35. DIRECT_ADDR       equ 1000b             ; прямая адресация памяти
    36. REG_EXPR       equ 10000b             ; регистр
    37. VALID_REF       equ 100000b             ; валидное выражение
    38. MEM_SS_EXPR       equ 1000000b           ; память относительно SS регистра
    39. EXTER_LABEL_EXPR   equ 10000000b           ; внешняя метка
    40. VIMM_EXPR       equ (VALID_REF OR IMM_EXPR)     ;
    41. align_proc MACRO
    42. IFDEF __MINIMAL_SIZE__
    43.    align 1
    44. ELSE
    45.    align 16
    46. ENDIF
    47. ENDM
    48. align_data MACRO
    49. IFDEF __MINIMAL_SIZE__
    50.    align 1
    51. ELSE
    52.    align 4
    53. ENDIF
    54. ENDM
    55.  
    56. @MEMSET MACRO Buf:req, value:req, count:req
    57.    LOCAL pBuf
    58.    push   edi
    59.    IF @InStr(1, <&Buf>, <&>) EQ 1
    60.      pBuf equ @SubStr(<&Buf>, 2)
    61.      IF ((OPATTR pBuf) AND DIRECT_ADDR) OR ((OPATTR pBuf) AND LABEL_EXPR)
    62.        mov   edi, offset pBuf
    63.      ELSE
    64.        lea   edi, pBuf
    65.      ENDIF
    66.    ELSEIFDIFI <Buf>, <edi>
    67.      mov   edi, Buf
    68.    ENDIF
    69.    IF value EQ 0
    70.    xor     eax, eax
    71.    ELSEIFDIFI <value>,<eax>
    72.    mov     eax, value
    73.    ENDIF
    74.    mov     ecx, (count+3)/4   ; count - bytes
    75.    rep stosd
    76.    pop     edi
    77.    EXITM <>
    78. ENDM
    79.  
    80. CVIRTUAL MACRO name_method:REQ, langType:REQ, retType:REQ, protoDef:VARARG
    81.    LOCAL sz1, sz2
    82.    pDef CATSTR <TYPEDEF PROTO >,<&langType&>,< (&retType&)>
    83.    IFNB <protoDef>
    84.      pDef CATSTR pDef, <, >, <&protoDef>
    85.    ENDIF
    86.    IFDEF curClass
    87.    sz2 CATSTR <_>, curClass, <_&name_method>   ;; _curClass_method
    88.    ELSE
    89.    sz2 CATSTR <_>, <_&name_method>
    90.    ENDIF
    91.    % &sz2 &pDef
    92. ;;   % echo &sz2 &pDef
    93.    % sz1 typedef PTR &sz2
    94.    % name_method sz1 ?
    95. ENDM
    96. ;=============================================================
    97.  
    98. char           typedef byte
    99. ;double           typedef real8
    100. true           equ 1
    101. false           equ 0
    102. MAX_STACK         equ 128
    103.  
    104. stOperation struct   ; (sizeof = 8 bytes)
    105.    CVIRTUAL   func, <FASTCALL>, <VOIDARG>, a:ptr real8, b:ptr real8
    106.    priority   sdword ?
    107. stOperation ends
    108. .data
    109. ;----------------------------------------------------------------------------
    110. .code
    111. ; СТАРТОВЫЙ КОД
    112. mainCRTStartup proc C
    113. local argc:dword, argv:LPVOID, environ:LPVOID, _si:STARTUPINFOA
    114.    mov     _si.cb, sizeof STARTUPINFOA
    115.    invoke   GetStartupInfoA, addr _si
    116.    invoke   __getmainargs, addr argc, addr argv, addr environ, 0, addr _si
    117.    invoke   main, argc, argv, environ
    118.    invoke   ExitProcess, eax
    119. mainCRTStartup endp
    120. ;----------------------------------------------------------------------------
    121. align_proc
    122. _add proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    123. ; a equ ecx, b equ edx
    124.    fld     real8 ptr [a]
    125.    fadd   real8 ptr [b]
    126.    fstp   real8 ptr [a]
    127.    ret
    128. _add endp
    129.  
    130. align_proc
    131. _sub proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    132.    fld     real8 ptr [a]
    133.    fsub   real8 ptr [b]
    134.    fstp   real8 ptr [a]
    135.    ret
    136. _sub endp
    137.  
    138. align_proc
    139. _mul proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    140.    fld     real8 ptr [a]
    141.    fmul   real8 ptr [b]
    142.    fstp   real8 ptr [a]
    143.    ret
    144. _mul endp
    145.  
    146. align_proc
    147. _div proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    148.    fld     real8 ptr [a]
    149.    fdiv   real8 ptr [b]
    150.    fstp   real8 ptr [a]
    151.    ret
    152. _div endp
    153.  
    154. align_proc
    155. main proc C argc:dword, argv:ptr, environ:ptr
    156. local level:dword, EndPtr:ptr char, stack_oper@end:dword
    157. local stack_value[MAX_STACK]:real8, stack_oper[MAX_STACK]:stOperation
    158. local func_token[256]:stOperation
    159. order     = 2
    160.    printf("Calculator expression.\n")
    161.    lea     edi, func_token
    162.    ASSUME   edi:ptr stOperation, ebx:ptr char
    163.    ;обнулим массив func_token
    164.    @MEMSET   (edi, 0, sizeof func_token)
    165.    lea     edi, [edi+'*'*8]
    166.    mov     [edi+'+'*8-'*'*8].func, offset _add
    167.    mov     [edi+'-'*8-'*'*8].func, offset _sub
    168.    mov     [edi+'*'*8-'*'*8].func, offset _mul
    169.    mov     [edi+'/'*8-'*'*8].func, offset _div
    170.    or     [edi+'+'*8-'*'*8].priority, 1
    171.    or     [edi+'-'*8-'*'*8].priority, 1
    172.    or     [edi+'*'*8-'*'*8].priority, 2
    173.    or     [edi+'/'*8-'*'*8].priority, 2
    174.    mov     level, ecx
    175.    ;удалим пробелы
    176.    ASSUME   esi:ptr char
    177.    mov     eax, argv
    178.    mov     ebx, [eax+1*4]
    179.    push   ebx
    180.    .for (esi=ebx ::ebx++, esi++)
    181.      .while ([esi]==' ' || [esi]==9)
    182.        inc     esi
    183.      .endw
    184.      mov     al, [esi]
    185.      mov     [ebx], al
    186.      .break .if (!al)
    187.    .endfor
    188.    pop     ebx
    189.    ASSUME   esi:ptr real8
    190.    lea     esi, stack_value[-8]   ;
    191.    lea     edi, stack_oper[-8]     ;
    192.    mov     stack_oper@end, edi
    193.    ;mov     ebx, CSTR("18/(-7-(1+1))*3-(2+(1-2))/10.5*(10*10)")   ;// для отладки в IDA Pro
    194.    .while (true)
    195.      .for (:[ebx]=='(':ebx++)
    196.        add     level, order
    197.      .endfor
    198.      invoke   crt_strtod, ebx, addr EndPtr
    199.      add     esi, 8
    200.      mov     ebx, EndPtr
    201.      fstp   [esi]
    202.      .for (:[ebx]==')':ebx++)
    203.        sub     level, order
    204.      .endfor
    205.      .if (![ebx])   ;// строка закончилась
    206.        .for (:edi>stack_oper@end: edi-=8, esi-=8);   stack@dec (edi), stack@dec (esi)
    207.          invoke   [edi].func, addr [esi-8], addr [esi]
    208.        .endfor
    209.        mov     edx, level
    210.        sar     edx, 1   ;/=order
    211.        .if (!edx)
    212.          mov     edx, argv
    213.          printf("%s = %.10f\n", [edx+1*4], [esi])
    214.        .else
    215.          push   edx
    216.          .if (sdword ptr edx>0)
    217.            ;printf("There is no closing parentheses: %d\n", edx)
    218.            push   CSTR("There is no closing parentheses: %d",0Dh,0Ah)
    219.          .else
    220.            ;printf("There is no opening parentheses: %d\n", edx)
    221.            push   CSTR("There is no opening parentheses: %d",0Dh,0Ah)
    222.          .endif
    223.          call   crt_printf
    224.          add     esp, 8
    225.        .endif
    226.        xor     eax, eax
    227.        ret
    228.      .endif
    229.      movzx   edx, [ebx]
    230.      mov     eax, func_token[edx*8].priority     ;eax - priority
    231.      add     eax, level
    232.      .for (:edi>stack_oper@end && [edi].priority >= eax: edi-=8, esi-=8);   stack@dec (edi), stack@dec (esi)
    233.        push   eax
    234.        invoke   [edi].func, addr [esi-8], addr [esi]
    235.        pop     eax
    236.      .endfor
    237.      movzx   edx, [ebx]
    238.      mov     ecx, func_token[edx*8].func
    239.      .break .if(!ecx)
    240.      add     edi, 8
    241.      mov     [edi].func, ecx
    242.      mov     [edi].priority, eax
    243.      inc     ebx
    244.    .endw
    245.    ASSUME   ebx:nothing, edi:nothing, esi:nothing
    246.    printf("unknown token '%c'\n", edx)
    247.    xor     eax, eax
    248.    inc     eax
    249.    ret
    250. main endp
    251.  
    252. end mainCRTStartup
    253.  
    Батник
    Код (Text):
    1. @echo off
    2. ..\..\..\uasm246_x86\bin\uasm32 /c /coff "calc.asm"
    3. ..\..\..\uasm246_x86\bin\polink /SUBSYSTEM:CONSOLE "calc.obj"
    4. if exist "calc.obj" del "calc.obj"
    5. pause
    А потом переделал на С/С++
    Код (C++):
    1. // Консольное утилита для вычисления выражений     (c) NanoBot
    2. #include <iostream>
    3. #define   MAX_STACK   128
    4. #define   order     2
    5.  
    6. void __fastcall add(double *a, double *b) { *a += *b; }
    7. void __fastcall sub(double *a, double *b) { *a -= *b; }
    8. void __fastcall mul(double *a, double *b) { *a *= *b; }
    9. void __fastcall div(double *a, double *b) { *a /= *b; }
    10.  
    11. int main(int argc, char** argv) {
    12.    struct stOperation {
    13.      void   set(void (__fastcall *f)(double *,double *), int p) { this->func = f; this->prior = p; };
    14.      void (__fastcall *func)(double *a, double *b);
    15.      int     prior;
    16.    }     TokFunc[128], stack_oper[MAX_STACK], *spOper = &stack_oper[-1], *stack_oper_end = spOper;
    17.    double   stack_value[MAX_STACK], *spValue = &stack_value[-1];
    18.    int     level=0, prior;
    19.    memset(TokFunc, 0, sizeof(TokFunc));
    20.    TokFunc['+'].set(add, 1); TokFunc['-'].set(sub, 1); TokFunc['*'].set(mul, 2); TokFunc['/'].set(div, 2);
    21.    printf("Calculator expression.\n");
    22.    for (char* p0 = argv[1], *p1 = p0; ; p0++, p1++) {
    23.      while(*p1==' ' || *p1==9) ++p1;
    24.      *p0 = *p1;
    25.      if(!*p1) break;
    26.    }
    27.    for (char* pStr = argv[1]; ; ++pStr) {
    28.      for (; *pStr == '('; level += order, ++pStr);
    29.      *++spValue = strtod(pStr, &pStr);
    30.      for (; *pStr == ')'; level -= order, ++pStr);
    31.      if (!*pStr) break;   // строка закончилась
    32.      char   token = !(*pStr&(~0x7F)) ? *pStr : 0;   // ограничем токены кодами 0..127
    33.      prior = TokFunc[token].prior + level;
    34.      for (; spOper>stack_oper_end && spOper->prior >= prior; spOper--, spValue--)
    35.        spOper->func(&spValue[-1], &spValue[0]);
    36.      auto    f = TokFunc[token].func;
    37.      if (!f) { printf("unknown token '%c'\n", *pStr); return 1; }
    38.      (++spOper)->set(f, prior);
    39.    }
    40.    for (; spOper>stack_oper_end; spOper--, spValue--)
    41.      spOper->func(&spValue[-1], &spValue[0]);
    42.    if(!level)
    43.      printf("%s = %.10f\n", argv[1], *spValue);
    44.    else if((level/=order)>0)
    45.      printf("There is no closing parentheses: %d\n", level);
    46.    else
    47.      printf("There is no opening parentheses: %d\n", level);
    48.    return 0;
    49. }
    В результате на ассемблере программа весит 1.5 кб(с линкером PoLink.exe), а на С++ 7.5 VS2010, и 9.5 кб с vs2017.
     
    James Anderson нравится это.
  5. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    а асм-листовка от компиля мокрых что показывает? что-то прирост размерчика мощный.
    а gcc пробовал?
    хмм.. а на этом уасм х64 лабать можно? чой-то мне кажется под вынью староватые тулзы для Асма.
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 дек 2008
    Сообщения:
    1.629
    когда вы сравниваете свою реализацию на асме с сишечкой по скорости или размеру, надо учитывать то, что по-умолчанию сишечка добавляет в исполняемый файл свой рантайм... если убрать рантайм и смержить секции, то на выходе получите такой же бинарь, как от асма... и готов поспорить, что добрая половина этого форума не сможеь реализовать какой-нить маломальски непростой алгоритм на асме (хотя бы мд5 или рц4) так, чтобы он обогнал по скорости сишечку со всеми оптимизациями...
     
    UbIvItS нравится это.
  7. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    Пожалуй, согласен с твоими словами: я смог обогнать лишь опосля очень извратного кода :)
     
  8. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    Ну да, компиляторы M$ и Intel хорошо оптимизируют код, а M$ VS C++ ещё не плохо уменьшает размер по сравнению с интелом. Но размер, получается, на ассемблере, всё равно меньше. И плюс ещё то, что компилятор иногда тупит по страшному, например, делает не инлайн функцию, когда надо это сделать при любом раскладе, разве что если запрещено делать инлайн функции. Ещё замечал, что иногда вставляет явный мёртвый код, хотя в исходниках всё нормально. Так же не использует некоторые выкрутасы, вроде byte i=0;do{ ...;++i;}while (i); городит свою конструкцию. Короче, на С/С++ нормальный код получается если программист по возможности использует низкоуровневый стиль кода, тогда и исполняемый код хороший получается.
    И ещё интересно, когда написал код на UASM, создал exe файл и проанализировал его в IDA Pro и Hex-rays, и тот подсказал как правильно аналогичный код создать на С/С++, вуаля и файл cpp готов.:scratch_one-s_head:
     
  9. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    всё-таки сравнивать размеры на малых кодах не совсем верно == вот если генериться портянка хотя бы на 100кб бинарник, то уже можно посмотреть в процентном соотношение, а так вес статики (прикрученной компилем) превалирует.
    с gcc, кстати, подобные проблемы можно лечить :)
     
  10. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    1.893
    Rel,

    > добрая половина этого форума не сможеь реализовать какой-нить маломальски непростой алгоритм на асме (хотя бы мд5 или рц4) так, чтобы он обогнал по скорости сишечку со всеми оптимизациями...

    А ничего что профайл садится в ядре, а не на машинных циклах в юм ?
     
  11. Rel

    Rel Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 дек 2008
    Сообщения:
    1.629
    а ничего...
     
  12. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    И всё равно ассемблер рулит.
    Код (ASM):
    1.  
    2. Reflect_bit MACRO value:req, ref:req, count_bit:req
    3. ;// перетаскиваем биты через CF. В результате итерация цикла выполняется за 2 такта
    4. ;// --->
    5. ;// [76543210]\ ;rcr
    6. ;//  \
    7. ;// [CF]
    8. ;//   <---  /
    9. ;// [76543210]/ ;rcl
    10. align 16
    11. .repeat
    12. rcr     ref, 1 ;shr
    13. rcl value, 1
    14. dec     count_bit
    15. .until (zero?)
    16. EXITM <value>
    17. ENDM
    18.  
    Не имею понятие как реализовать такой код на С/С++, всего то два такта, в С получается гораздо больше команд. Ладно.
    Код (ASM):
    1. .if (ecx)
    2. movzx edx, [ebx]
    3. align 16
    4. .repeat
    5. xor dl, al ;1
    6. lea ebx, [ebx+1] ;1
    7. ; lea ecx, [ecx-1]
    8. shr eax, 8 ;2
    9. mov esi, crc32_table[edx*4] ;2
    10. mov dl, [ebx] ;3
    11. xor eax, esi ;3
    12. ; jecxz _break
    13. ;dec ecx;, 1 ;4
    14. .untilcxz; (false) ;5zero?
    15. .endif
    16.  
    Так же экспериментировал с CRC32 на асме итерация получается 5 тактов, а на С++ 6 тактов VS2017 и 7 тактов VS2010, после оптимизации кода 6 тактов на VS2010, VS2017 оптимизирует лучше, справился без оптимизации. И ещё, на более мощных процессорах итерация может выполнятся до 3 тактов, процессор с макс 4 ИнструкцииЗаТакт за 4 такта должен справится.
    Файл прилагаю, компилятор UASM.
     

    Вложения:

    • crc32.rar
      Размер файла:
      4,4 КБ
      Просмотров:
      2
    • crc32.cpp.rar
      Размер файла:
      1.012 байт
      Просмотров:
      1
    Последнее редактирование: 9 июл 2018
  13. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    1.893
    Intro,

    На современных системах инструкции выполняются не по тактам, точнее такого понятия даже не существует. Такты для инструкций считаются на простейших контроллерах.
    Мне интересно каким же образом вы измеряли такты", если счётчика с должным разрешением не существует :sarcastic:
     
    TermoSINteZ нравится это.
  14. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    Ещё на первых пнях появились счётчики тактов, а такты они и в Африке такты. А инструкция RDTSC позволяет их считывать в рег. eax:edx. Разве не знали, или думаете точность не очень, нормальная точность, не надо ляля, дополнительные инструкции CPUID позволяют разгрузить конвейер, точность 0-2 такта. Так что всё точно, лишь ассемблер позволяет вытянуть из процессора все возможности, компиляторы по прежнему тупят, просто вероятно это сам С/С++ кривой, надо Cx86 сделать, отличается дополнительным набором операторов для этого процессора, циклическая прокрутка бит, поиск бит, кол. бит, и так далее, и без всяких дурацких интринсиксов(дурацкое слово), всё красиво и удобно.
     
  15. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
  16. Rel

    Rel Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 дек 2008
    Сообщения:
    1.629
    CRC все равно слишком простой алгоритм, чтобы мериться письками, возьмите SHA-256, MD5, AES, ну или хотя бы RC4... в стандартной библиотеки языка Go все эти алгоритмы специально реализованы на ихнем ассемблере, тк сам компилятор языка Go не достаточно хорошо оптимизирует их... сделайте свою реализацию и сравните по скорости с реализацией на C...
     
  17. im.

    im. Member

    Публикаций:
    0
    Регистрация:
    16 сен 2017
    Сообщения:
    119
    То что тут показано быстрее будет работать на Javascript который компилируется в ассемблер на лету и более удобен для разработки, а оснвные алгосы поедут быстрее на .NET, потому как он генерит код под хостовый ЦПУ и может легко применять расширенные инструкции SSE и пр. Даже сам WASM существует на ПХП и JS :-)
    А про 9кб, неудивительно заюзав stdLib, напиши прямой код и получишь 2 кб, а лу ше не писать совсем с такой то стилистикой оформления ))))
     
  18. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    3.484
    в плане буста кодов скрипты действительно можно использовать весьма весело.. еть, можно сказать, есь сама обитель морфа. Однако, скрипты сложно сделать безопасными == элемент секуры и стабильности в сущности может обрушить весь буст. :)
     
  19. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    1.893
    Intro,

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

    Есть есчо один нюанс:

    > movzx edx, [ebx]

    Это и далее означает что ваш код выполняется в протектед мод, те под мультизадачной осью. А в таком случае каждое измерение будет спонтанным, рандом. Нужен цикл из огромного числа итераций, для определения усреднённой статистики.
     
  20. Intro

    Intro Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    77
    Не знаю, у меня ровно 5 тактов показывает мой код, и 6 тактов код на С++, и ещё код на С++ я смотрел в IDA Pro, там есть лишние команды, и мне не удалось его оптимизировать, всё равно свой код лепит. Я могу добиться 3 тактов за итерацию на процессоре с 5 МаксИнструкцийЗаТакт. Возможно более новые версии компиляторов смогут оптимальней делать. А сейчас это не получается, туповатый компилятор забывает что eax и al это один и тот же регистр, только что получает доступ к младшему байту, короче обязательно вставляет инструкцию преобразования movzx, которая и отнимает лишний такт.
    Процессор AMD Athlon II X4 640, да староват однако, в любом случае мой код оптимальней и быстрей на 20%.
    Что ещё, тесты делал на WinXP SP3 и Win7 SP1, это важно, более новые ОСи работают кривей, обязательно сработает прерывание, и поломает статистику. Так же делал тесты на ноутбуке, не помню название, Intel, код работает аккурат в два раза медленней, хотя поколение процессора более высокое. Так что возможно на новых процессорах счётчик тактов работает криво совсем, это плохо.
    И ещё, на Win7 надо два раза кликнуть тестовой программки, первый раз показывает около 8 тактов, а потом точно 5 тактов, антивирус, защитник виндоса, не знаю что там прерывает тест.
    Оптимальней всего закомментированный код
    Код (ASM):
    1.              lea edi, crc32_table
    2.              xor edx, edx
    3.              mov dl, [ebx]
    4.              align 16
    5. .repeat
    6.              xor dl, al      ;1
    7.              inc ebx         ;1
    8.              mov ecx, [edi+edx*4] ;2
    9.              shr eax, 8         ;2
    10.              xor eax, ecx     ;3
    11.              mov dl, [ebx] ;3
    12.              dec esi             ;4
    13. .until (zero?)          ;5
    Что-то форум уродовает форматирования, убирает табуляторы.
    Цифры это такты, операции за 1-3 такта выполняются последовательно, счётчик цикла может выполнится параллельно, и того 5 тактов.