2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4  След.
 
 Re: Быстрое вычисление функции exp(x)
Сообщение25.03.2014, 20:40 


10/04/12
705
pi-314 в сообщении #840657 писал(а):
Сравнил скорость выполнения нижеприведенного кода в FPC и Delphi 7.
Delphi 7: 1x; FPC: 1.4x.

А флаги компиляции?

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение25.03.2014, 22:13 
Заслуженный участник


12/07/07
4528
На мой взгляд, за счет оптимизации кода, в частности выбора компилятора, большого выигрыша не получить. Для примера рассмотрим тестовую программу на паскале из сообщения mustitz. Эта программа содержит только продолжительный простой цикл и поэтому позволяет хорошую оптимизацию. Я написал два варианта процедуры Main с ассемблерными вставками [и слегка модифицировал процедуру на паскале (по соображениям удобства общие константы объявлены глобально)].
В первой процедуре (MainA1) оптимизация состоит в том, что Sum и X во время цикла находятся в регистрах сопроцессора.
Во второй процедуре (MainA2) дополнительно в стек загружены Delta и Xmax, для того чтобы сложение и сравнение выполнять не с переменной в памяти, а с переменной в регистре. Кроме того, вместо вызова функции exp её тело вставлено в текст процедуры [Последнее и дало львиную долю ускорения вычислений по сравнению с MainA1.].

код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program test;
{$A-,B-,C+,D+,E-,F-,G+,H+,I-,J+,K-,L+,M-,N+,O+,P+,Q+,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}
{$MINSTACKSIZE $00004000}
{$MAXSTACKSIZE $00100000}
{$IMAGEBASE $00400000}
{$APPTYPE CONSOLE}
uses windows;

Const
 X0:    Single   = -10.0;
 Xmax:  Single   =  10.0;
 Delta: Double = 0.000001;

procedure MainA1();
var
  Sum: Extended;
begin
 asm
  fldz
  fld    X0
@1:
  fld       st              {story X}
  call   system.@EXP
  faddp  st(2),  st    {Sum := Sum + Exp(X)}
  fadd    Delta          {X := X + Delta}
  fcom   Xmax         {X < Xmax ?}
  fstsw  ax
  sahf
  jbe     @1              {until X < Xmax}
  fstp    st(2)
  fstp    Sum
 end;
 WriteLn(Sum);
end;

procedure MainA2();
var
  Sum: Extended;
begin
 asm
  fld    Xmax
  fld    Delta
  fldz
  fld       X0
@1:
  fld       st              {story X}
{"Borland" exp}
  fldl2e                   { y := x*log2e;      }
  fmul
  fld       st(0)         { i := round(y);     }
  frndint
  fsub    st(1),   st  { f := y - i;        }
  fxch    st(1)         { z := 2**f          }
  f2xm1
  fld1
  fadd
  fscale               { result := z * 2**i }
  fstp    st(1)
{/"Borland" exp}
  faddp  st(2),  st    {Sum := Sum + Exp(X);}
  fadd    st,     st(2) {X := X + Delta}
  fucom st(3)         {X < Xmax ?}
  fstsw  ax
  sahf
  jbe   @1             {until X < Xmax}
  fstp   st(2)
  fstp   st(1)
  fstp   st(1)
  fstp   Sum
 end;
 WriteLn(Sum);
end;

procedure Main();
var
  X: Extended;
  Sum: Extended;
begin
  X := X0;
  Sum := 0.0;
  repeat
    if X > Xmax then Break;
    Sum := Sum + Exp(X);
    X := X + Delta;
  until False;
  WriteLn(Sum);
end;
var
 PerformanceCount, SaveCount, Delta1, Delta2: TLargeInteger;

begin
  Writeln('PAS ---------');
  QueryPerformanceCounter(SaveCount);
  Main();
  QueryPerformanceCounter(PerformanceCount);
  Delta1:= PerformanceCount-SaveCount;
  Writeln(Delta1);
  Writeln('ASM1 ---------');
  QueryPerformanceCounter(SaveCount);
  MainA1();
  QueryPerformanceCounter(PerformanceCount);
  Delta2:=PerformanceCount-SaveCount;
  Writeln(Delta2);
  Writeln((Delta1 - Delta2)/Delta1*100:5:3, '%');
  Writeln('ASM2 ---------');
  QueryPerformanceCounter(SaveCount);
  MainA2();
  QueryPerformanceCounter(PerformanceCount);
  Delta2:=PerformanceCount-SaveCount;
  Writeln(Delta2);
  Writeln((Delta1 - Delta2)/Delta1*100:5:3, '%')
end.

Программа компилировалась в Delphi 5 c включенной оптимизацией и выключенными проверками. Тестовый расчет выполнен на Р3. MainA1 выполнялась приблизительно на 7.8% быстрее Main, а MainA2 — на 12.4%. Лучшую оптимизацию, чем в MainA2, мне с ходу придумать трудно. Более того, данный пример является «хорошо оптимизируемым», а в других случаях в вычислительных задачах оптимизация будет меньше. На мой взгляд, возиться с выбором компилятора для вычислительной задачи, когда выигрыш составляет не более 15% — просто абсурдно (лучше, чем человек на ассемблере, компилятор с ЯВУ всё равно не сделает).
Берём Delphi (если владеем Паскалем и можем позволить себе приобрести) и не теряем время на тесты.
Думаю, в вычислительных задачах стоит обратить внимание на модификацию алгоритма, которая может привести к большему выигрышу.

Редактирование: добавлено уточнение («по сравнению с MainA1») в начале сообщения, 26.03.14

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение25.03.2014, 22:54 
Заслуженный участник


09/05/12
25179
GAA в сообщении #840724 писал(а):
На мой взгляд, за счет оптимизации кода, в частности выбора компилятора, большого выигрыша не получить.

GAA в сообщении #840724 писал(а):
Тестовый расчет выполнен на Р3. MainA1 выполнялась приблизительно на 7.8% быстрее Main, а MainA2 — на 12.4%. Большей оптимизации, чем в MainA2, мне сходу придумать трудно. Более того, данный пример является «хорошо оптимизируемым», а в других случаях в вычислительных задачах оптимизация будет меньше. На мой взгляд, возиться с выбором компилятора для вычислительной задачи, когда выигрыш составляет не более 15% — просто абсурдно (лучше, чем человек на ассемблере, компилятор с ЯВУ всё равно не сделает).


У меня нет Delphi, поэтому я в качестве отправного пункта брал исходный вариант (с Main) для FPC, который компилировался с -O3. Ну и заодно я перевел программу на Фортран (сделав буквальный "подстрочник"), лучший результат для нее показал IFC.

Разница во времени выполнения - чуть более чем в четыре раза. Согласитесь, это несколько больше, чем 15%.

P.S. А нет, можно еще лучше. Рекордсменом в данном случае оказался Open64, его результат обгоняет FPC в пять с небольшим раз.

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение25.03.2014, 23:24 
Заслуженный участник


12/07/07
4528
Я никогда не пользовался fpc. Если он в 4-ре раза хуже некоторого Фортрана, то его надо просто выбросить.

Я занимался тщательным сравнением компиляторов (в вычислительных задачах)около пятнадцати лет назад. Компиляторы с Фортрана проигрывали ассемблеру совсем немного (проценты) и столько же выигрывали у компиляторов Cи. TP очень сильно проигрывал TC, но с переходом к Delphi и совершенствованию процессоров разница уменьшилась.

Повторюсь. Уже пример mustitz довольно искусственный. В реальных вычислительных программах получить 15% выигрыш по сравнению с Delphi не просто.

Если Ваш фортран дает четырехкратный выигрыш, то приведите ассемблерный код процедуры Main. Этот код должен быть не менее чем в два раза быстрее кода Delphi. В это (в предположении использования инструкций 386/387 процессора) поверить трудно.

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 00:17 
Заслуженный участник


09/05/12
25179
GAA в сообщении #840751 писал(а):
Если Ваш фортран дает четырехкратный выигрыш, то приведите ассемблерный код процедуры Main. Этот код должен быть не менее чем в два раза быстрее кода Delphi. В это (в предположении использования инструкций 386/387 процессора) поверить трудно.

А зачем в 2014 году использовать инструкции 80386/80387?

Код получился в 13 кБ размером. Это, конечно, с комментариями, но без них разбираться с происходящим там тяжело. Соответственно, сюда это класть, наверное, все же не стоит.

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 07:54 
Заслуженный участник


12/07/07
4528
Pphantom в сообщении #840759 писал(а):
А зачем в 2014 году использовать инструкции 80386/80387?
Сравнивать эффективность компиляторов имеет смысл на инструкциях для одних и тех же процессоров, да и в теме ранее говорилось об игре с 387 («Ну и еще можно поиграться с -mfpmath=sse,387 и -mtune»). Впрочем, в данном случае это не имеет особого значения. Использование более продвинутого набора команд позволяет получить значительное ускорение на x86 в более специфическом исходном тексте. Давайте договоримся сравнивать код все же для x86 в широком смысле, пусть даже расширенного до 64.

В моём сообщении текст процедуры MainA2 с ассемблерной вставкой составляет не более 756 байт. Пусть, чтобы не спорить, ассемблерный текст всей процедуры будет весить 2 килобайта (+ вход, завершение и вызов функции вывода в файл).

Пожалуйста: 1) проверьте, не захватили ли вы кроме кода Main код остальной части программы; 2) если не захватили, то уберите в исходном тексте на Фортране вызов функции вывода на экран — это поможет сократить ассемблерный код функции Main.

Со вторым предложением можно поступить так. Вместо текста на Паскале из сообщения mustitz перевести на Фортран и скомпилировать
код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program Test;

function Main:extended;
const
  Delta: Extended = 0.000001;
var
  X: Extended;
  Sum: Extended;
begin
  X := -10.0;
  Sum := 0.0;
  repeat
    if X > 10.0 then Break;
    Sum := Sum + Exp(X);
    X := X + Delta;
  until False;
 Main:= Sum;
end;

begin
  WriteLn(Main);
end.

Если всё так плохо (и Вы не путаете ассемблерный листинг и объектный файл), то оставьте комментарии для входа и выхода из функции. В остальных местах удалите. [Зная суть выполняемых действий, легко будет понять ассемблерный листинг.] И вставляйте в тег syntax.

Pphantom, заинтриговали. Ассемблерный листинг (или текст из отладчика на уровне мнемоник инструкций процессора) в студию!

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 08:09 


10/04/12
705
GAA в сообщении #840724 писал(а):
Лучшую оптимизацию, чем в MainA2, мне сходу придумать трудно.

SIMD? prefetch?

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 08:24 


27/02/14
22
mustitz в сообщении #840675 писал(а):
А флаги компиляции?

FPC: -MObjFPC -Scghi -O3 -OoUNCERTAIN -vewnhi -Filib\i386-win32 -Fu. -FUlib\i386-win32\ -l
Delphi 7: включена оптимизация, отключены все проверки

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 16:37 


27/02/14
22
кстати, обнаружил неплохой ресурс по сравнению производительности различных компиляторов ЯП.
В частности, FPC vs IFC:
http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=all&lang=ifc&lang2=fpascal&data=u32

Как видно, IFC чаще выигрывает, но есть ряд задач где они идут вровень.

P.s. сравнения выполнены под Linux, интересно, можно ли выводы переносить на Win...

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 19:13 
Заслуженный участник


12/07/07
4528
mustitz в сообщении #840808 писал(а):
SIMD? prefetch?
mustitz, попробуйте привести ассемблерный текст для функции Main. Крайне желательно в варианте без вызова функции вывода на экран; чтобы проще читать было. И всё станет ясно.

По поводу отставания программы скомпилированной FPC от скомпилированной Delphi
Я заглянул в FPC 2.6.2 RTL
В файле \i386\math.inc находим
код: [ скачать ] [ спрятать ]
Используется синтаксис ASM
function fpc_exp_real(d : ValReal) : ValReal;assembler;compilerproc;
      var
        cw1,cw2: word;
      asm
        // comes from DJ GPP
        fldt        d
        fldl2e
        fmulp       %st,%st(1)
        fstcw       CW1
        fstcw       CW2
        fwait
        andw        $0xf3ff,CW2
        orw         $0x0400,CW2
        fldcw       CW2
        fld         %st(0)
        frndint
        fldcw       CW1
        fxch        %st(1)
        fsub        %st(1),%st
        f2xm1
        fld1
        faddp       %st,%st(1)
        fscale
        fstp        %st(1)
     end;
Aаналогичный текст для x86_64 в файле \x86_64\math.inc (отсутствует fwait, но это не принципиально)
код: [ скачать ] [ спрятать ]
Используется синтаксис ASM
    function fpc_exp_real(d : ValReal) : ValReal;assembler;compilerproc;
       var
         oldcw,newcw: word;
       asm
            // comes from DJ GPP
            fldt        d
            fldl2e
            fmulp       %st,%st(1)
            fstcw       oldcw
            fstcw       newcw
            andw        $0xf3ff,newcw
            orw         $0x0400,newcw
            fldcw       newcw
            fld         %st(0)
            frndint
            fldcw       oldcw
            fxch        %st(1)
            fsub        %st(1),%st
            f2xm1
            fld1
            faddp       %st,%st(1)
            fscale
            fstp        %st(1)
      end;

Этот текст можно сравнить с текстом функции exp в RTL Delphi, приведенным в моём сообщении в качестве вставки в функцию MainA2 (у кого RTL под рукой также могут найти текст функции в модуле “\RTL\Sys\system.pas” под именем _exp).

Во-первых, в Delphi аргумент передаётся через стек fpu. Как правило, это увеличивает скорость выполнения за счёт уменьшения лишнего чтения из стека; кроме того, это позволяет в Delphi не включать в подпрограмму стандартный вход и выход, поскольку нет локальных параметров, т.е. не включать:
Код:
PUSH    EBP              ;Present if Locals <> 0 or Params <> 0
MOV     EBP,ESP          ;Present if Locals <> 0 or Params <> 0
SUB     ESP,Locals       ;Present if Locals <> 0
...
MOV     ESP,EBP          ;Present if Locals <> 0
POP     EBP              ;Present if Locals <> 0 or Params <> 0

[Такая передача параметра (через стек fpu) является привилегией некоторых функций модуля system и недоступна пользователю при написании своих процедур и функций.]

Как выглядит стандартный вход и выход в FPC, я не знаю, но что-то в любом случае должно быть.

Во-вторых, в Delphi на этапе инициализации fpu выставляется такое значение fpu control word (CW), которое позволяет выполнять frndint в функции exp без изменения CW. В Delphi любая процедура, которая изменяет CW, должна перед завершением его восстановить.

Этими двумя моментами видимо и объясняется более медленное выполнение программы скомпилированной FPC по сравнению с Delphi. [Дальше нужно смотреть в отладчике исполняемый код, сгенерированный FPC и Delphi. Может ещё какая-то мелочь вылезет.]

[Я впервые залез в RTL FPC, поэтому мог не туда посмотреть. Надеюсь, знатоки FPC поправят или дополнят, а читатель пусть перепроверит.]

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 20:29 
Заслуженный участник


09/05/12
25179
GAA в сообщении #840805 писал(а):
Сравнивать эффективность компиляторов имеет смысл на инструкциях для одних и тех же процессоров, да и в теме ранее говорилось об игре с 387
Но нас ведь интересует не рафинированная производительность компиляторов, а возможность провести нужные вычисления максимально эффективно. Если один из сравниваемых компиляторов не поддерживает современные инструкции процессоров - это просто означает, что им не надо пользоваться.

GAA в сообщении #840805 писал(а):
Пожалуйста: 1) проверьте, не захватили ли вы кроме кода Main код остальной части программы;
Да, речь шла о программе целиком. Вот нужный участок для IFC (вывод остался на месте):
код: [ скачать ] [ спрятать ]
Используется синтаксис ASM
       .align    16,0x90
        .globl MAIN__
MAIN__:
..B1.1:                         # Preds ..B1.0
..___tag_value_MAIN__.1:                                        #1.9
        pushq     %rbp                                          #1.9
..___tag_value_MAIN__.3:                                        #
        movq      %rsp, %rbp                                    #1.9
..___tag_value_MAIN__.4:                                        #
        andq      $-128, %rsp                                   #1.9
        subq      $128, %rsp                                    #1.9
        movq      $0x000000000, %rsi                            #1.9
        movl      $3, %edi                                      #1.9
        call      __intel_new_feature_proc_init                 #1.9
                                # LOE rbx r12 r13 r14 r15
..B1.12:                        # Preds ..B1.1
        stmxcsr   (%rsp)                                        #1.9
        movl      $__NLITPACK_0.0.1, %edi                       #1.9
        orl       $32832, (%rsp)                                #1.9
        ldmxcsr   (%rsp)                                        #1.9
        call      for_set_reentrancy                            #1.9
                                # LOE rbx r12 r13 r14 r15
..B1.2:                         # Preds ..B1.12
        movl      $1, %esi                                      #6.7
        lea       (%rsp), %rdi                                  #6.7
        movq      $0x1208384ff00, %rdx                          #6.7
        movl      $__STRLITPACK_1.0.2, %ecx                     #6.7
        xorl      %eax, %eax                                    #6.7
        lea       64(%rsp), %r8                                 #6.7
        movq      $0, (%rsp)                                    #6.7
        movq      $8, 64(%rsp)                                  #6.7
        movq      $__STRLITPACK_0, 72(%rsp)                     #6.7
        movq      $4, 80(%rsp)                                  #6.7
        call      for_open                                      #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.3:                         # Preds ..B1.2
        movsd     .L_2il0floatpacket.1(%rip), %xmm2             #6.7
        pxor      %xmm3, %xmm3                                  #6.7
        movsd     .L_2il0floatpacket.2(%rip), %xmm1             #6.7
        movsd     %xmm3, 104(%rsp)                              #6.7
        movsd     %xmm2, 96(%rsp)                               #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.4:                         # Preds ..B1.13 ..B1.3
        movsd     96(%rsp), %xmm0                               #6.7
        comisd    .L_2il0floatpacket.2(%rip), %xmm0             #6.7
        ja        ..B1.6        # Prob 18%                      #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.5:                         # Preds ..B1.4
        movsd     96(%rsp), %xmm0                               #6.7
        call      exp                                           #6.7
                                # LOE rbx r12 r13 r14 r15 xmm0
..B1.14:                        # Preds ..B1.5
        movsd     %xmm0, 88(%rsp)                               #6.7
        movsd     .L_2il0floatpacket.2(%rip), %xmm0             #6.7
        mulsd     96(%rsp), %xmm0                               #6.7
        call      exp                                           #6.7
                                # LOE rbx r12 r13 r14 r15 xmm0
..B1.13:                        # Preds ..B1.14
        movsd     .L_2il0floatpacket.3(%rip), %xmm3             #6.7
        movsd     88(%rsp), %xmm1                               #6.7
        mulsd     %xmm3, %xmm1                                  #6.7
        divsd     %xmm0, %xmm1                                  #6.7
        movsd     104(%rsp), %xmm2                              #6.7
        movsd     96(%rsp), %xmm4                               #6.7
        addsd     %xmm1, %xmm2                                  #6.7
        addsd     %xmm3, %xmm4                                  #6.7
        movsd     %xmm2, 104(%rsp)                              #6.7
        movsd     %xmm4, 96(%rsp)                               #6.7
        jmp       ..B1.4        # Prob 100%                     #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.6:                         # Preds ..B1.4                  # Infreq
        movsd     104(%rsp), %xmm3                              #
        lea       (%rsp), %rdi                                  #6.7
        lea       88(%rsp), %r8                                 #6.7
        movl      $-1, %esi                                     #6.7
        movq      $0x1208384ff00, %rdx                          #6.7
        movl      $__STRLITPACK_2.0.2, %ecx                     #6.7
        xorl      %eax, %eax                                    #6.7
        movq      $0, (%rsp)                                    #6.7
        movsd     %xmm3, 88(%rsp)                               #6.7
        call      for_write_seq_lis                             #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.7:                         # Preds ..B1.6                  # Infreq
        movsd     104(%rsp), %xmm3                              #
        lea       (%rsp), %rdi                                  #6.7
        movl      $1, %esi                                      #6.7
        movq      $0x1208384ff00, %rdx                          #6.7
        movl      $__STRLITPACK_3.0.2, %ecx                     #6.7
        lea       96(%rsp), %r8                                 #6.7
        xorl      %eax, %eax                                    #6.7
        movq      $0, (%rsp)                                    #6.7
        movsd     %xmm3, 96(%rsp)                               #6.7
        call      for_write_seq_lis                             #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.8:                         # Preds ..B1.7                  # Infreq
        movl      $1, %esi                                      #6.7
        lea       (%rsp), %rdi                                  #6.7
        movq      $0x1208384ff00, %rdx                          #6.7
        movl      $__STRLITPACK_4.0.2, %ecx                     #6.7
        xorl      %r8d, %r8d                                    #6.7
        xorl      %eax, %eax                                    #6.7
        movq      $0, (%rsp)                                    #6.7
        call      for_close                                     #6.7
                                # LOE rbx r12 r13 r14 r15
..B1.9:                         # Preds ..B1.8                  # Infreq
        movl      $1, %eax                                      #8.1
        movq      %rbp, %rsp                                    #8.1
        popq      %rbp                                          #8.1
..___tag_value_MAIN__.6:                                        #
        ret                                                     #8.1
        .align    16,0x90
..___tag_value_MAIN__.8:                                        #


-- 26.03.2014, 20:33 --

pi-314 в сообщении #841030 писал(а):
кстати, обнаружил неплохой ресурс по сравнению производительности различных компиляторов ЯП.

Это очень плохой ресурс. Если посмотреть на исходные коды, которые использовались для сравнения, обнаружится, что их автор(ы) на всех языках писали подстрочные переводы с C (вернее, урезанного почти до чистого C подмножества C++). Соответственно, почти везде код для соответствующего языка предельно неэффективен, в частности, верно это и для Фортрана.

 Профиль  
                  
 
 Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 20:40 


10/04/12
705
Код:
$ $ gcc -S -O3 -mfpmath=sse,387 -ffast-math -mtune=native t                                                       est.c -lm
$ cat test.s
код: [ скачать ] [ спрятать ]
Используется синтаксис ASM
        .file   "test.c"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC7:
        .string "%Le"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB25:
        .cfi_startproc
        subq    $24, %rsp
        .cfi_def_cfa_offset 32
        fldt    .LC0(%rip)
        fldz
        flds    .LC2(%rip)
        fldl    .LC3(%rip)
        flds    .LC4(%rip)
        fldl2e
        fld1
        fxch    %st(5)
        jmp     .L3
        .p2align 4,,10
        .p2align 3
.L5:
        fld     %st(0)
        fmul    %st(4), %st
        fld     %st(0)
        frndint
        fsubr   %st, %st(1)
        fxch    %st(1)
        f2xm1
        fadd    %st(6), %st
        fscale
        fstp    %st(1)
        fxch    %st(6)
        fxch    %st(1)
        fxch    %st(4)
        fxch    %st(1)
.L3:
        faddp   %st, %st(6)
        fxch    %st(3)
        fadd    %st(2), %st
        fcomi   %st(1), %st
        jbe     .L5
        fstp    %st(0)
        fstp    %st(0)
        fstp    %st(0)
        fstp    %st(0)
        fstp    %st(0)
        fstpt   (%rsp)
        movl    $.LC7, %esi
        movl    $1, %edi
        xorl    %eax, %eax
        call    __printf_chk
        xorl    %eax, %eax
        addq    $24, %rsp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE25:
        .size   main, .-main
        .section        .rodata.cst16,"aM",@progbits,16
        .align 16
.LC0:
        .long   602199267
        .long   3194736043
        .long   16368
        .long   0
        .section        .rodata.cst4,"aM",@progbits,4
        .align 4
.LC2:
        .long   3240099840
        .section        .rodata.cst8,"aM",@progbits,8
        .align 8
.LC3:
        .long   2696277389
        .long   1051772663
        .section        .rodata.cst4
        .align 4
.LC4:
        .long   1092616192
        .ident  "GCC: (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) 4.5.3"
        .section        .note.GNU-stack,"",@progbits
 

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 21:14 
Заслуженный участник


04/05/09
4589
Pphantom в сообщении #841178 писал(а):
Вот нужный участок для IFC (вывод остался на месте):
Этот код не соответствует тому, что на Паскале. Больше похоже на численное интегрирование, причём не просто экспоненты, а чего-то посложнее. По крайней мере экспонента вызывается 2 раза в цикле.
Далее, IFC вовсю использует SSE и собственно код вычисления экспоненты отсутствует, т.к. в SSE нет такой инструкции. Всё спрятано в библиотечной функции exp.

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение26.03.2014, 23:44 
Заслуженный участник


09/05/12
25179
venco в сообщении #841213 писал(а):
Этот код не соответствует тому, что на Паскале. Больше похоже на численное интегрирование,

Ну вообще-то это и есть численное интегрирование экспоненты. :D

Собственно функция (точнее, процедура) выглядела так
код: [ скачать ] [ спрятать ]
Используется синтаксис Fortran
  subroutine Main

    open(1,file="Data.txt")
    X=-10.0
    Su=0.0
    do
      if(X>10.0) exit
      Su=Su+exp(X)*Delta/exp(10.0*X)
      X=X+Delta
    end do
    write(*,*) Su
    write(1,*) Su
    close(1)
  end subroutine Main
 

В общем-то это "подстрочный" перевод, хотя и с глобальными переменными. Изменения чисто косметические: дескриптор файла превратился в "1", переменную Sum я переименовал в Su (поскольку Sum - встроенная функция языка).

venco в сообщении #841213 писал(а):
Далее, IFC вовсю использует SSE и собственно код вычисления экспоненты отсутствует, т.к. в SSE нет такой инструкции. Всё спрятано в библиотечной функции exp.

Конечно. Но, еще раз повторяю, исходно речь шла не о соревнованиях авторов компиляторов в одинаковых рафинированных условиях, а о том, как эффективнее решать реальные задачи.

 Профиль  
                  
 
 Re: Быстрое вычисление функции exp(x)
Сообщение27.03.2014, 01:13 
Заслуженный участник


04/05/09
4589
Эффективнее можно сделать разными способами. Лучший - проинтегрировать аналитически. :-)
Далее можно:
0. использовать более точные методы (Симпсона) и уменьшить число итераций.
1. преобразовать формулу, чтобы экспоненту считать только раз за цикл.
2. использовать много-поточность.
3. использовать на полную катушку SSE - вычислять 2 а то и 4 экспоненты за раз.
4. для численного метода можно уменьшить точность вычисления экспоненты, используя полиномы покороче.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 55 ]  На страницу Пред.  1, 2, 3, 4  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group