Производительность 2.0 vs 1.010

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Сообщение anotherche » 31.10.2005 16:31:16

Код тестовой программы (просто длинный цикл с вещественными вычислениями), откомпилированный с одинаковыми опциями исполняется на 20%(atlon) - 100%(p4) медленней. Почему?
anotherche
 

Сообщение Sniper » 31.10.2005 17:44:02

Разница в архитектуре у них ОГРОМНАЯ
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение STAKANOV » 31.10.2005 21:22:57

anotherche писал(а): Код тестовой программы (просто длинный цикл с вещественными вычислениями), откомпилированный с одинаковыми опциями исполняется на 20%(atlon) - 100%(p4) медленней. Почему?

Это разница между чем и чем?
А ОС какая?
Я правильно понял - один код был собран fpc 2.0.0 и fpc 1.010 и затем оба ипоняемых модуля были запущены на ПК с Atlon и ПК с P4 ?
А можно пример кода?
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение anotherche » 01.11.2005 13:17:20

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


Это разница между чем и чем?...
Я правильно понял - один код был собран fpc 2.0.0 и fpc 1.010 и затем оба ипоняемых модуля были запущены на ПК с Atlon и ПК с P4 ?

да, все так.

Код: Выделить всё
program Test_PC;
uses crt,dos{,graph};
Var i,j,k, itnum : Longint;
   c,dT : double;
        {##################################################}
Function Time : double;
Var Ho,Mi,Se,Se1 : word; dH,dM,dS,dS1 : double;
begin
         GetTime(Ho,Mi,Se,Se1); dH:=Ho; dM:=Mi; dS:=Se; dS1:=Se1;
         Time:=(3600.0*dH +60.0*dM +dS +0.01*dS1); end;
          {########################################}
begin
itnum:=30;

WriteLn('###############       ','   Test of PC ,DOS','    ###############');
WriteLn('Time for PC 486        133 Mhz, Real   = ',16.53:15:9,'  Sec');
WriteLn('Time for PC PENTIUM    150 Mhz, Real   = ', 5.93:15:9,'  Sec');
WriteLn('Time for PC PENTIUM(1) 166 Mhz, Real   = ', 5.10:15:9,'  Sec');
WriteLn('Time for PC PENTIUM-2  233 Mhz, Real   = ', 4.61:15:9,'  Sec');
WriteLn('Time for PC Celeron    400 Mhz, Real   = ', 2.74:15:9,'  Sec');
WriteLn('Time for PC PENTIUM    225 Mhz, Real   = ', 2.69:15:9,'  Sec');
WriteLn('Time for PC Celeron    333 Mhz, Real   = ', 3.24:15:9,'  Sec');

WriteLn('Time for PC 486        133 Mhz, Protect= ',21.69:15:9,'  Sec');
WriteLn('Time for PC PENTIUM    150 Mhz, Protect= ',12.69:15:9,'  Sec');
WriteLn('Time for PC PENTIUM(1) 166 Mhz, Protect= ',11.64:15:9,'  Sec');
WriteLn('Time for PC PENTIUM-2  233 Mhz, Protect= ',10.11:15:9,'  Sec');
WriteLn('Time for PC Celeron    400 Mhz, Protect= ', 5.66:15:9,'  Sec');
WriteLn('Time for PC PENTIUM    225 Mhz, Protect= ', 5.33:15:9,'  Sec');
WriteLn('Time for PC Celeron    333 Mhz, Protect= ', 6.81:15:9,'  Sec');
WriteLn('Time for PC Athlon XP 1700 Mhz, Protect= ', 0.72:15:9,'  Sec');
WriteLn('                        Time for FREE PASCAL');
WriteLn('Time for PC Athlon    2000 Mhz, Protect= ', 0.160:15:9,'  Sec');
WriteLn('Time for PC Intel     3150 Mhz, Protect= ', 0.118:15:9,'  Sec');
WriteLn('Time for PC Intel     3300 Mhz, Protect= ', 0.113:15:9,'  Sec');
WriteLn('Time for PC Athlon XP 2800+Mhz, Protect= ', 0.150:15:9,'  Sec');

dT:=Time;
c:=0.0;
For k:=1 to itnum do begin
For j:=1 to 33 do begin
For i:=1 to 12345 do begin
c:=c +Ln(0.12*(i+j+k)) +sqrt(0.19*(i+j+k)) +exp(Ln(0.26*(i+j+k))) +sin((i+j+k)*0.34) +cos((i+j+k)*0.77);
end;
end;
end;
dT:=Time-dT;
WriteLn('Time for this PC            = ',dT/itnum:15:9,'  Sec');
Repeat Until KeyPressed;
end.
anotherche
 

Сообщение STAKANOV » 01.11.2005 14:38:42

ОС FreeBSD
P III, 866Мгц

FPC 1.0.10:
Код: Выделить всё
###############          Test of PC ,DOS    ###############
...
Time for this PC            =     0.331333333  Sec

FPC 2.0.0:
Код: Выделить всё
###############          Test of PC ,DOS    ###############
...
Time for this PC            =     0.318666667  Sec


Сначала порадовался потом позапускав несколько раз и получив очень(!!!) разные результаты понял, что тест не объективен для многозадачных систем.
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Сообщение PVOzerski » 01.11.2005 15:02:38

Вы бы asm-код сравнили, что ли... Благо, можно попросить компилятор его сохранить.
PVOzerski
постоялец
 
Сообщения: 109
Зарегистрирован: 19.05.2005 13:45:10
Откуда: СПб

Сообщение anotherche » 03.11.2005 12:29:37

Сначала порадовался потом позапускав несколько раз и получив очень(!!!) разные результаты понял, что тест не объективен для многозадачных систем.

Конечно, все это понятно. Но вся эта многозадачность, она же управляема. Выключаешь все, что мешает и вперед. Ошибка конечно будет всегда, но не катастрофичная. У меня она никогда не была хуже чем во втором знаке. Так что разницу в 20%, а тем более в 2 раза видно очень хорошо.
Судя по Вашему результату наблюдается тенденция - чем длиннее конвеер у процессора тем больше падение производительности.

Вы бы asm-код сравнили, что ли... Благо, можно попросить компилятор его сохранить


Сравнил. Я, честно говоря, с ассемблером не на ты, но случай кажется простым. Отличия небольшие. Мне кажется, что основная разница из-за того, что в случае fpc_2.0.0 в конце цикла вставляется команда wait. Как я понял она ждет пока сопроцессор чего-то там доделает (хотя вроде как эта команда означает разное для старых и новых процессоров и у новых это что-то связанное с исключениями).
Ну вот пример (он не для исходного кода, а для кода попроще, для наглядности). Это кусок кода, соответсвующий только циклу
Код: Выделить всё
For j:=1 to 10000 do begin
For i:=1 to 10000 do begin
c:=c +Ln((i+j)*0.001);
end;
end;


ассемблер, выданный fpc_1.0.6 (десятой у меня не было на тот момент)
Код: Выделить всё
;[9] For j:=1 to 10000 do begin
   movl   $1,_J
   .balign 4,144
.L8:
; Register %eax allocated
; [10] For i:=1 to 10000 do begin
   movl   $1,_I
   .balign 4,144
.L13:
; Register %eax allocated
; [11] c:=c +Ln((i+j)*0.001);
   movl   _I,%eax
   addl   _J,%eax
   pushl   %eax
; Register %eax released
   fildl   (%esp)
; Register %edi allocated
   popl   %edi
; Register %edi released
   fldt   .L18             ; это коэффициент 0.001
   fmulp   %st,%st(1)
   fldln2
   fxch
   fyl2x
   faddl   _C
   fstpl   _C
; Register %eax allocated
   cmpl   $10000,_I
   jge   .L12
   incl   _I
   jmp   .L13
; Register %eax released
.L12:
; Register %eax allocated
   cmpl   $10000,_J
   jge   .L7
   incl   _J
   jmp   .L8


а вот то, что дал fpc_2.0.0
Код: Выделить всё
; [9] For j:=1 to 10000 do begin
   movl   $1,U_P$MYTEST_J
   decl   U_P$MYTEST_J
   .balign 4
.L8:
   incl   U_P$MYTEST_J
; [10] For i:=1 to 10000 do begin
   movl   $1,U_P$MYTEST_I
   decl   U_P$MYTEST_I
   .balign 4
.L11:
   incl   U_P$MYTEST_I
; Register %eax allocated
; [11] c:=c +Ln((i+j)*0.001);
   movl   U_P$MYTEST_I,%eax
   addl   U_P$MYTEST_J,%eax
; Temp -4,4 allocated
   movl   %eax,-4(%ebp)
; Register %eax released
   fildl   -4(%ebp)
; Temp -4,4 released
   fldt   _$PROGRAM$_L14     ; это коэффициент 0.001
   fmulp   %st,%st(1)
   fldln2
   fxch
   fyl2x
   faddl   U_P$MYTEST_C
   fstpl   U_P$MYTEST_C
   fwait                                            ; а вот он wait
   cmpl   $10000,U_P$MYTEST_I
   jl   .L11
   cmpl   $10000,U_P$MYTEST_J
   jl   .L8


видны и другие отличия (правда мне думается они не принципиальные), и вот почему я грешу на wait. Приведенный код работает с одинаковой скоростью. И если вместо логарифма поставить синус, косинус или корень тоже все работает с одинаковой скоростью. Но вот если взять экспоненту, тут то все и начинается. Скорость падает почти вдвое. Экспонента, в отличие от остальных функций там вызывается не прямо (не как операция процессора), а как подпрограмма (где-то зашитая в freepascal), так что ее пришлось смотреть через IDA. Так вот, там видно, что опять таки отличие кода выдаваемого 106 от 200 заключается в инструкциях wait, их там несколько (кажется три, сейчас не помню точно).
Кто понимает? Действительно ли дело в wait-ах? Зачем fpc2.0.0 добавляет их в код? Может ли fpc компилировать свой asm листинг? (хочется проверить - убрать wait-ы из листинга сделанного в 2.0.0 и скомпилировать результат)
anotherche
 

Сообщение Илья Аввакумов » 03.11.2005 13:23:26

В древности (8088) команда привыполнении инструкции fwait сопроцессор ждал, когда основной процессор будет готов принять данные от сопроцессора (не уверен, так как воспроизвожу по памяти, а было это ой как давно) Я был уверен, что сейчас эта команда не используется.
Илья Аввакумов
новенький
 
Сообщения: 50
Зарегистрирован: 04.05.2005 15:06:42
Откуда: Екатеринбург

Сообщение anotherche » 03.11.2005 17:01:28

В древности (8088) команда привыполнении инструкции fwait сопроцессор ждал, когда основной процессор будет готов принять данные от сопроцессора (не уверен, так как воспроизвожу по памяти, а было это ой как давно) Я был уверен, что сейчас эта команда не используется.

по уточненным сведениям она теперь используется как запрос на возникновение исключения при вещественных вычислениях . То есть в принципе компилятор прав, он предлагает код который в случае чего вызовет исключение сразу после его возникновения (иначе это происходит при следующем вещественном вычислении, а оно может произойти очень далеко от точки ошибки), но опять же он не прав :) ведь в этом цикле вещественные вычисления идут подряд друг за другом и по большому счету не так уж и важно чтобы об ошибке стало известно прямо в срок. Эту проверку можно отложить вообще до конца цикла :). А еще лучше чтобы у компилятора была опция . Я вот сейчас вспомнил что в более привычном для меня MSVC были подобные опции, почитал msdn и точно - у них есть три режима компиляции вещественных вычислений - fast, precise (по умолчанию) и strict (вот там то компилятор и добавляет wait инструкции после каждого вещественного вычисления). Может у fpc и так есть что-то подобное? (я вообще-то паскалем занимаюсь очень эпизодически, только когда шеф попросит, так что не уверен). А если таких опций у fpc нет, то не плохо бы разработчикам их добавить. Я так думаю :)
anotherche
 

Сообщение PVOzerski » 03.11.2005 18:29:49

ИМХО, это стоило бы с переводом на аглицкий переслать в FPC developers Mailing List (официальный). Может, кто займется? А то мне переводить некогда :)
PVOzerski
постоялец
 
Сообщения: 109
Зарегистрирован: 19.05.2005 13:45:10
Откуда: СПб

Сообщение anotherche » 08.11.2005 11:39:33

Все, я разобрался в вопросе. Проверил напрямую - собрал из ассемблера два варианта с wait'ами и без них. И оказалось... что wait здесь ни при чем :). А виновата одна инструкция в коде вычисления экспоненты. Впрочем эта инструкция тоже связана с обработкой исключений.
Вот экспонента, которую делает fpc_106
Код: Выделить всё
fn_exp proc
   push    ebp
   mov     ebp,esp
   fld     tbyte ptr [ebp+8]
   fldl2e
   fmulp   st(1),st
   fstcw    tmpcw1
   fstcw   tmpcw2
   and     tmpcw2,0F3FFh
   or       tmpcw2,400h
   fldcw   tmpcw2
   fld       st(0)
   frndint
   fldcw   tmpcw1
   fxch    st(1)
   fsub    st,st(1)
   f2xm1
   fld1
   faddp   st(1),st
   fscale
   fstp      st(1)
   jmp     loc_004027A5
loc_004027A5:
   leave
   ret     0Ch
fn_exp endp


А вот fpc_200

Код: Выделить всё
fn_exp proc
   push    ebp
   mov     ebp,esp
   sub     esp,0Ch
   fld     tbyte ptr [ebp+8]
   fldl2e
   fmulp   st(1),st
   fstcw   tmpcw1
   fstcw   tmpcw2
   wait
   and     tmpcw2,0F3FFh
   or       tmpcw2,400h
   fldcw   tmpcw2
   fld     st(0)
   frndint
   fldcw   tmpcw1
   fxch    st(1)
   fsub    st,st(1)
   f2xm1
   fld1
   faddp   st(1),st
   fscale
   fstp    st(1)
   fclex
   jmp     loc_004027A5
loc_004027A5:
   leave
   ret     0Ch
fn_exp endp


Инструкция fclex очищает флаги исключений в регистре Status Word и очищение это как видно отнимает нимало производительности (на p4 замедление счета в 2 раза). Похоже, что в 2.0.0 просто перестраховываются при расчете экспоненты.
anotherche
 


Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru
cron