Помогите оптимизировать код.

Тема в разделе "WASM.A&O", создана пользователем Lof, 3 авг 2007.

  1. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Код (Text):
    1. #define NUM 256*1024*1024
    2.  
    3. double calc5()
    4. {
    5.     double pi = 0.0;
    6.     double two = 2.0;
    7.     int i = 0;
    8.     double four = 4.0;
    9.  
    10.     _asm
    11.     {
    12.         mov ecx, 0;
    13.         fld two;
    14.         fld1;
    15.         fld pi;
    16.  
    17. labela:
    18.         fld st(2);
    19.         mov i, ecx;
    20.         fimul i;
    21.         fadd st,st(2);
    22.         fld st(2);
    23.         fxch;
    24.         fdivp st(1),st;
    25.  
    26.         mov eax,ecx;
    27.         and eax,1;
    28.         cmp eax,1;
    29.         jne Parity;
    30.         // нечетно
    31.         fsubp st(1),st;
    32.         jmp endec;
    33. Parity:
    34.         // четно
    35.         faddp st(1),st;
    36. endec:
    37.         inc ecx;
    38.         cmp ecx, NUM;
    39.         jl labela;
    40.         fmul four;
    41.         fstp pi;
    42.     }
    43.  
    44.     return pi;
    45. }
     
  2. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    Код (Text):
    1. and eax,1;
    2.         cmp eax,1; убрать эту строчку
    3.         jne Parity;
     
  3. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Хм... я так понял реальное ускорение может дать только использование SSE?
     
  4. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    Код (Text):
    1. mov eax, ecx
    2. and eax, 1
    Код (Text):
    1. test ecx, 1
    А, вообще, разворот вдвое уберёт ветвление внутри цикла :)
     
  5. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Переменную цикла можно на уменьшение забить, а не на увеличение.
    Инетересно было бы ещё на формулу самих вычислений поглядеть, может быть она не очень рациональна.

    Вообще я бы на си на писал и поглядел))) При таком раскладе, компилятор может неплохой код даст.
     
  6. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Ага можно вообще без ветвления. код, inc(ecx), код, inc(ecx), jl Только это скорости не прибавляет.

    Пробовал. Тогда ответ не верный получается.

    Так я и написал сначала на си. А потом решил обыграть компилятор. Нифига. Код мой выполняется с той же скоростью... :dntknw:
     
  7. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    Код (Text):
    1.         mov     ecx, NUM
    2.         fldz
    3.         fld1
    4.         fld1
    5.         fadd    st(1), st
    6.         jmp     entr
    7. labela: fadd    st, st(1)
    8. entr:   fld1
    9.         fdiv    st, st(1)
    10.         faddp   st(3), st
    11.         dec     ecx
    12.         jz      labelb
    13.         fadd    st, st(1)
    14.         fld1
    15.         fdiv    st, st(1)
    16.         fsubp   st(3), st
    17.         dec     ecx
    18.         jnz     labela
    19. labelb: fstp    st(0)
    20.         fstp    st(0)
    21.         fmul    four
    22.         fstp    pi
    Хотя выигрыша почти нет :dntknw: Зато размер :)

    Код (Text):
    1. fldpi
    2. fstp pi
    :)
     
  8. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    Код (Text):
    1. double calc5() {
    2.     double pi = 0.0;
    3.     double four = 4.0;
    4.     int i = 1;
    5.     _asm {
    6.         mov     ecx, NUM
    7.         fldz
    8. labela: fld1
    9.         fidiv   i
    10.         add     i, 2
    11.         faddp   st(1), st
    12.         sub     ecx, 2
    13.         fchs
    14.         jnz     labela
    15.         fmul    four
    16.         fstp    pi
    17.     }
    18.     return pi;
    19. }
     
  9. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Читер! :)

    А последний код сильно быстрее(сейчас не могу потестить)?
     
  10. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    1/1 - 1/3 + 1/5 - 1/7 + 1/9 - ... = arctg 1

    Неправда! Верный :) Только скорость от этого падает с ~2 до ~4с :dntknw:

    Если вместо i забить [eax], размер цикла ровно 16 байт :)
    В C нема align?
     
  11. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Циклы выравивать некоторые компиляторы могут, не которые нет.
    Если для данных, то в вижаке align есть....
     
  12. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Код не правильно работает. Точнее не идентичен исходному. :dntknw:
     
  13. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    Чё не так? Ошибка в результате? У меня правильно считал.
    Ну, а не идентичен - что конкретно не нравицца?
     
  14. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Прошу прощения, но то что в тегах code я частично не вижу он причине отсутствия скролбара на дочерних окнах, а посему прошу пояснить мне что призван делать приведенный код? ;)
     
  15. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Да в результате. Возьми мой оригинальный код и свой. Сделай NUM = 10, 100, 1000 и посмотри на результат. Твой код аналогичен NUM/2.
     
  16. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    :)
    sub ecx, 1
    :)
     
  17. Lof

    Lof New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    14
    Тогда все верно :)
    Только этот код медленее твоего же с dec.
    Но быстрее моего оригинального.
     
  18. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Можно решить проблему с чередованием знаков и заодно сократить число делений, если обрабатывать пары слагаемых
    1/(x+2)-1/(x+4) = 2/(x+2)*(x+4) - тут еще и 2 за скобку вынести
    Приимерно так:
    Код (Text):
    1.   mov ecx,Num
    2.   mov edx,ecx
    3.   shr ecx,1
    4.   fldz          //sum
    5.   fld1
    6.   fadd st0,st0  //2
    7.   fld st0
    8.   fadd st0,st0  //4
    9.   fld1          
    10.   fchs          //x = -1
    11. @loop:
    12.   fld st0
    13.   fadd st0,st2  //x+4
    14.   fxch s0,st1   //x'=x+4
    15.   fadd st0,st3  //x+2
    16.   fmul st0,st1  //(x+2)*(x+4)
    17.   fld1
    18.   fdivrp        //1/(x+2)*(x+4)
    19.   faddp st4,st0 //sum+=1/(x+2)*(x+4)
    20.   dec ecx
    21.   jnz @loop
    22.   fld st3
    23.   fadp st4,st0  //sum=sum*2
    24.   and edx,1     //проверка Num на нечетность
    25.   jz @skip
    26.   fadd st0,st2  //x+2
    27.   fld1
    28.   fdivrp        //1/(x+2)
    29.   fadd st3,st0
    30. @skip:
    31.   fstp st0
    32.   fstp st0  
    33.   fstp st0
    34.   fstp pi