LINUX.ORG.RU

Вновь о gfortran: удалось локализовать его медлительность


0

0

Оказалось, что gfortran сильно, СИЛЬНО, ОЧЕНЬ СИЛЬНО замедляется на вычислениях с двойной точностью. Т.е. использую REAL(4) - скорость сопоставима с платным компилером и Watcom-ом, разница хоть и есть, но не критичная. Однако, при использовании REAL(8) производительность падает в два с лишним раза, тогда как у платного менее, чем на 5%. Попытался найти опции в компилере, отвечающие за двойную точность и все, что с ней связано. Использовал в итоге следующие опции

-Wall -O3 -march=i686 -malign-double -mfpmath=sse -mmmx -msse2 -ffast-math

Процессор на машине pentium4m, но никакой особой разницы по сравнению с неуказанием опции -march я не нашел.

Может, кто знает, что еще можно покрутить в нем?

anonymous

Я думаю, что это не связано непосредственно со скоростью выполнения операций с двойной точностью процессором. Попробуй изготовить тестовый пример небольшого размера который будет подвержен этой проблеме, и посмотри на результат компиляции в виде ассемблерного листинга. Сравни с другими компиляторами. Это самый прямой и простой путь на мой взгляд.

anonymous
()
Ответ на: комментарий от anonymous

Я в этом более чем уверен, скорее он генерит какой-то странный код для двойной точности. С ассемблером надо будет попробовать (хоть я в нем и очень слабо разбираюсь, если не сказать больше - не разбираюсь совсем).

anonymous
()
Ответ на: комментарий от Vadim_Z

>И иногда -O3 хуже, чем -O2.

Читал в багзилле к gfortran-у, что -O1 выдает нормальный код, а уже на -O2 идет замедление, а с -O3 уже вообще никак.

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

anonymous
()
Ответ на: комментарий от anonymous

>очень слабо разбираюсь, если не сказать больше - не разбираюсь совсем

Тогда запости листинги сюда

anonymous
()
Ответ на: комментарий от anonymous

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

Очень вероятно, что он обходит баги в процессорах, дабы гарантировать соблюдение стандарта

anonymous
()
Ответ на: комментарий от anonymous

Вот код ассемблера:
.file "test.f95"
.text
.globl _MAIN__
.def _MAIN__; .scl 2; .type 32; .endef
_MAIN__:
pushl %ebp
movl %esp, %ebp
subl $56, %esp
subl $12, %esp
pushl $0
pushl $0
pushl $0
pushl $127
pushl $68
call __gfortran_set_std
addl $32, %esp
movl $-1717986918, %eax
movl $1076140441, %edx
movl %eax, -32(%ebp)
movl %edx, -28(%ebp)
movl $-858993459, %eax
movl $1075236044, %edx
movl %eax, -8(%ebp)
movl %edx, -4(%ebp)
fldl -32(%ebp)
fmull -8(%ebp)
faddl -32(%ebp)
fstpl -16(%ebp)
movl $0x4124cccd, %eax
movl %eax, -36(%ebp)
movl $0x40b66666, %eax
movl %eax, -40(%ebp)
flds -36(%ebp)
fadds -40(%ebp)
fadds -36(%ebp)
fstps -20(%ebp)
leave
ret
.def __gfortran_set_std; .scl 2; .type 32; .endef

сгенерированный на
PROGRAM TEST

REAL(8) X, Y, Z
REAL(4) A, B, C
X = 10.3_8
Y = 5.7_8
Z = X*Y+X
A = 10.3_4
B = 5.7_4
C = A+B+A
END PROGRAM

anonymous
()
Ответ на: комментарий от anonymous

Извиняюсь, этот мог быть преобразован в константы: уж совсем просто код хотел сделать.

Теперь вот на это: PROGRAM TEST

REAL(8) X, Y, Z REAL(4) A, B, C READ *, X, Y Z = X*Y+X READ *, A, B C = A+B+A END PROGRAM

Генериться командой gfrotran test.f95 -S вот это:

.file "test.f95" .section .rdata,"dr" LC0: .ascii "test.f95\0" .text .globl _MAIN__ .def _MAIN__; .scl 2; .type 32; .endef _MAIN__: pushl %ebp movl %esp, %ebp subl $344, %esp subl $12, %esp pushl $0 pushl $0 pushl $0 pushl $127 pushl $68 call __gfortran_set_std addl $32, %esp movl $LC0, -320(%ebp) movl $5, -316(%ebp) movl $5, -324(%ebp) movl $128, -328(%ebp) subl $12, %esp leal -328(%ebp), %eax pushl %eax call __gfortran_st_read addl $16, %esp subl $4, %esp pushl $8 leal -32(%ebp), %eax pushl %eax leal -328(%ebp), %eax pushl %eax call __gfortran_transfer_real addl $16, %esp subl $4, %esp pushl $8 leal -40(%ebp), %eax pushl %eax leal -328(%ebp), %eax pushl %eax call __gfortran_transfer_real addl $16, %esp subl $12, %esp leal -328(%ebp), %eax pushl %eax call __gfortran_st_read_done addl $16, %esp fldl -32(%ebp) fldl -40(%ebp) fmulp %st, %st(1) fldl -32(%ebp) faddp %st, %st(1) fstpl -8(%ebp) movl $LC0, -320(%ebp) movl $7, -316(%ebp) movl $5, -324(%ebp) movl $128, -328(%ebp) subl $12, %esp leal -328(%ebp), %eax pushl %eax call __gfortran_st_read addl $16, %esp subl $4, %esp pushl $4 leal -20(%ebp), %eax pushl %eax leal -328(%ebp), %eax pushl %eax call __gfortran_transfer_real addl $16, %esp subl $4, %esp pushl $4 leal -16(%ebp), %eax pushl %eax leal -328(%ebp), %eax pushl %eax call __gfortran_transfer_real addl $16, %esp subl $12, %esp leal -328(%ebp), %eax pushl %eax call __gfortran_st_read_done addl $16, %esp flds -20(%ebp) flds -16(%ebp) faddp %st, %st(1) flds -20(%ebp) faddp %st, %st(1) fstps -12(%ebp) leave ret .def __gfortran_set_std; .scl 2; .type 32; .endef .def __gfortran_st_read; .scl 2; .type 32; .endef .def __gfortran_transfer_real; .scl 2; .type 32; .endef .def __gfortran_st_read_done; .scl 2; .type 32; .endef

anonymous
()
Ответ на: комментарий от anonymous

а если указать опции -march=pentium4m -O3, то вот это

.file "test.f95"
.section .rdata,"dr"
LC0:
.ascii "test.f95\0"
.text
.globl _MAIN__
.def _MAIN__; .scl 2; .type 32; .endef
_MAIN__:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $356, %esp
movl $0, 16(%esp)
movl $0, 12(%esp)
movl $0, 8(%esp)
movl $127, 4(%esp)
movl $68, (%esp)
call __gfortran_set_std
movl $LC0, -312(%ebp)
movl $5, -308(%ebp)
movl $5, -316(%ebp)
movl $128, -320(%ebp)
leal -320(%ebp), %ebx
movl %ebx, (%esp)
call __gfortran_st_read
movl $8, 8(%esp)
leal -24(%ebp), %eax
movl %eax, 4(%esp)
movl %ebx, (%esp)
call __gfortran_transfer_real
movl $8, 8(%esp)
leal -32(%ebp), %eax
movl %eax, 4(%esp)
movl %ebx, (%esp)
call __gfortran_transfer_real
movl %ebx, (%esp)
call __gfortran_st_read_done
movl $LC0, -312(%ebp)
movl $7, -308(%ebp)
movl $5, -316(%ebp)
movl $128, -320(%ebp)
movl %ebx, (%esp)
call __gfortran_st_read
movl $4, 8(%esp)
leal -16(%ebp), %eax
movl %eax, 4(%esp)
movl %ebx, (%esp)
call __gfortran_transfer_real
movl $4, 8(%esp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
movl %ebx, (%esp)
call __gfortran_transfer_real
movl %ebx, (%esp)
call __gfortran_st_read_done
addl $356, %esp
popl %ebx
popl %ebp
ret
.def __gfortran_set_std; .scl 2; .type 32; .endef
.def __gfortran_st_read; .scl 2; .type 32; .endef
.def __gfortran_transfer_real; .scl 2; .type 32; .endef
.def __gfortran_st_read_done; .scl 2; .type 32; .endef

anonymous
()
Ответ на: комментарий от anonymous

Извиняюсь, этот мог быть преобразован в константы: уж совсем просто код хотел сделать.
Теперь вот на это:

PROGRAM TEST

REAL(8) X, Y, Z
REAL(4) A, B, C
READ *, X, Y
Z = X*Y+X
READ *, A, B
C = A+B+A
END PROGRAM

Генериться командой gfrotran test.f95 -S вот это:

.file "test.f95"
.section .rdata,"dr"
LC0:
.ascii "test.f95\0"
.text
.globl _MAIN__
.def _MAIN__; .scl 2; .type 32; .endef
_MAIN__:
pushl %ebp
movl %esp, %ebp
subl $344, %esp
subl $12, %esp
pushl $0
pushl $0
pushl $0
pushl $127
pushl $68
call __gfortran_set_std
addl $32, %esp
movl $LC0, -320(%ebp)
movl $5, -316(%ebp)
movl $5, -324(%ebp)
movl $128, -328(%ebp)
subl $12, %esp
leal -328(%ebp), %eax
pushl %eax
call __gfortran_st_read
addl $16, %esp
subl $4, %esp
pushl $8
leal -32(%ebp), %eax
pushl %eax
leal -328(%ebp), %eax
pushl %eax
call __gfortran_transfer_real
addl $16, %esp
subl $4, %esp
pushl $8
leal -40(%ebp), %eax
pushl %eax
leal -328(%ebp), %eax
pushl %eax
call __gfortran_transfer_real
addl $16, %esp
subl $12, %esp
leal -328(%ebp), %eax
pushl %eax
call __gfortran_st_read_done
addl $16, %esp
fldl -32(%ebp)
fldl -40(%ebp)
fmulp %st, %st(1)
fldl -32(%ebp)
faddp %st, %st(1)
fstpl -8(%ebp)
movl $LC0, -320(%ebp)
movl $7, -316(%ebp)
movl $5, -324(%ebp)
movl $128, -328(%ebp)
subl $12, %esp
leal -328(%ebp), %eax
pushl %eax
call __gfortran_st_read
addl $16, %esp
subl $4, %esp
pushl $4
leal -20(%ebp), %eax
pushl %eax
leal -328(%ebp), %eax
pushl %eax
call __gfortran_transfer_real
addl $16, %esp
subl $4, %esp
pushl $4
leal -16(%ebp), %eax
pushl %eax
leal -328(%ebp), %eax
pushl %eax
call __gfortran_transfer_real
addl $16, %esp
subl $12, %esp
leal -328(%ebp), %eax
pushl %eax
call __gfortran_st_read_done
addl $16, %esp
flds -20(%ebp)
flds -16(%ebp)
faddp %st, %st(1)
flds -20(%ebp)
faddp %st, %st(1)
fstps -12(%ebp)
leave
ret
.def __gfortran_set_std; .scl 2; .type 32; .endef
.def __gfortran_st_read; .scl 2; .type 32; .endef
.def __gfortran_transfer_real; .scl 2; .type 32; .endef
.def __gfortran_st_read_done; .scl 2; .type 32; .endef

anonymous
()
Ответ на: комментарий от anonymous

Такое ощущение, что в случае -O3 вычисления типа Z = X*Y+X
компилятор просто выкинул, в связи с тем, что Z далее нигде не
используется. В тех листингах, где не выкинул они производятся
без всякой "эмуляции":

fldl -32(%ebp)
fldl -40(%ebp)
fmulp %st, %st(1)
fldl -32(%ebp)
faddp %st, %st(1)
fstpl -8(%ebp)

На самом деле это все не интересно, интересно вот что:
необходимо сделать какую-нибудь функцию исключительно с
числодробильней (без всяких READ, они сильно засоряют получившийся
ассемблерный листинг) и эквивалентную ей функцию с REAL(4) и
такую же по смыслу функцию на С. И убедится, что эффект воспроизводится
(т.е. С-вариант работает в 2 раза быстрее, и REAL(4) тоже в 2 раза
быстрее). Только после этого, рассматривая все 3 листинга вместе
можно попытаться чего-то понять.

anonymous
()
Ответ на: комментарий от anonymous

Метод Симпсона, функция зашита в самом методе для простоты. Функция имеет вид:

SIN(X2*X2)*X2 + SQRT(X2)

Вот этот код был создан бесплатной лицензией платного компилятора

Silverfrost FTN95/WIN32 Ver 5.10.0 simpson.F95 Sat Oct 20 18:39:07 2007

VS7

0001 MODULE SIMPSON AT 0 0002 !USE KND AT 0 0003 IMPLICIT NONE AT 0 0004 AT 0 0005 !INTEGER(4), PARAMETER:: DBL = 8 AT 0 0006 AT 0 0007 CONTAINS AT 0 0008 REAL(2) FUNCTION QUAD(A, B, N) !, F) AT 0 ; Start of FUNCTION SIMPSON!QUAD 00000000(3/1/4) push ebp 00000001(4/1/4) mov ebp,esp 00000003(5/1/4) push ebx 00000004(6/1/4) push esi 00000005(7/1/4) push edi 00000006(8/1/4) push eax 00000007(9/1/4) sub esp,=88 ; Adjusted later if temporaries allocated 0009 REAL(2), INTENT(IN):: A, B AT d 0010 INTEGER(4) N AT d 0011 !INTERFACE AT d 0012 ! PURE REAL(8) FUNCTION F(X) AT d 0013 ! REAL(8), INTENT(IN):: X AT d 0014 ! END FUNCTION AT d 0015 !END INTERFACE AT d 0016 REAL(2) H, H2 AT d 0017 REAL(2) X1, X2, X3 AT d 0018 REAL(2) F1, F2, F3 AT d 0019 H = (B - A) / N AT d 0000000d(10/5/11) mov eax,address of N 00000010(12/5/112) mov ecx,address of B 00000013(14/5/112) mov edi,address of A 00000016(11/5/11) qfild [eax] 00000018(13/5/112) dfld [ecx] 0000001a(15/5/112) dfsub [edi] 0000001c(16/4/6) fdivrp fr1,fr0 0000001e(17/3/7) dfstp H 0020 H2 = H / 2 AT 21 00000021(19/4/12) dfld H 00000024(20/4/12) dfdiv 2.0_2 0000002a(21/3/13) dfstp H2 <.....>

anonymous
()
Ответ на: комментарий от anonymous

Движок сайт задолбал уже: то сообщение большой, то строки коверкает,
то вообще ошибку выдает. Итак, еще раз

Метод Симпсона, функция зашита в самом методе для простоты. Функция имеет вид:
SIN(X2*X2)*X2 + SQRT(X2)

Вот этот код был создан бесплатной лицензией платного компилятора

Silverfrost FTN95/WIN32 Ver 5.10.0 simpson.F95 Sat Oct 20 18:39:07 2007

VS7

0001 MODULE SIMPSON AT 0
0002 !USE KND AT 0
0003 IMPLICIT NONE AT 0
0004 AT 0
0005 !INTEGER(4), PARAMETER:: DBL = 8 AT 0
0006 AT 0
0007 CONTAINS AT 0
0008 REAL(2) FUNCTION QUAD(A, B, N) !, F) AT 0
; Start of FUNCTION SIMPSON!QUAD
00000000(3/1/4) push ebp
00000001(4/1/4) mov ebp,esp
00000003(5/1/4) push ebx
00000004(6/1/4) push esi
00000005(7/1/4) push edi
00000006(8/1/4) push eax
00000007(9/1/4) sub esp,=88 ; Adjusted later if temporaries allocated
0009 REAL(2), INTENT(IN):: A, B AT d
0010 INTEGER(4) N AT d
0011 !INTERFACE AT d
0012 ! PURE REAL(8) FUNCTION F(X) AT d
0013 ! REAL(8), INTENT(IN):: X AT d
0014 ! END FUNCTION AT d
0015 !END INTERFACE AT d
0016 REAL(2) H, H2 AT d
0017 REAL(2) X1, X2, X3 AT d
0018 REAL(2) F1, F2, F3 AT d
0019 H = (B - A) / N AT d
0000000d(10/5/11) mov eax,address of N
00000010(12/5/112) mov ecx,address of B
00000013(14/5/112) mov edi,address of A
00000016(11/5/11) qfild [eax]
00000018(13/5/112) dfld [ecx]
0000001a(15/5/112) dfsub [edi]
0000001c(16/4/6) fdivrp fr1,fr0
0000001e(17/3/7) dfstp H

anonymous
()
Ответ на: комментарий от anonymous

0020 H2 = H / 2 AT 21
00000021(19/4/12) dfld H
00000024(20/4/12) dfdiv 2.0_2
0000002a(21/3/13) dfstp H2
0021 X1 = A AT 2d
0000002d(23/3/15) dfld [edi]
0000002f(24/3/15) dfstp X1
0022 X2 = X1 + H2 AT 32
00000032(26/4/113) dfld X1
00000035(27/4/113) dfadd H2
00000038(28/3/19) dfstp X2
0023 X3 = X1 + H AT 3b
0000003b(30/4/114) dfld X1
0000003e(31/4/114) dfadd H
00000041(32/3/22) dfstp X3

anonymous
()
Ответ на: комментарий от anonymous

0024 QUAD = 0 AT 44
00000044(34/3/24) mov (RESULT of QUAD)[4],=0
0000004b(35/3/24) mov (RESULT of QUAD),=0
0025 !F3 = X1*X1*X1*X1 - X1*X1*X1 + X1*X1 - 20.0*X1 - 7.0*SIN(X1) AT 52
0026 F3 = SIN(X1*X1)*X1 + SQRT(X1) AT 52
00000052(36/5/43) dfld X1
00000055(37/5/43) fsqrt
00000057(38/7/115) dfld X1
0000005a(39/7/115) fmul fr0,fr0
0000005c(40/6/37) fsin
0000005e(41/5/116) dfmul X1
00000061(42/4/117) faddp fr1,fr0
00000063(43/3/31) dfstp F3
00000066(45/3/49) jmp __N4
0000006b(46/3/49) align16
00000070(47/3/49) Label __N5
0027 DO WHILE (X3 .LE. B) AT 70
0028 F1 = F3 AT 70
00000070(48/5/51) dfld F3
00000073(49/5/51) dfstp F1
0029 !F2 = X2*X2*X2*X2 - X2*X2*X2 + X2*X2 - 20.0*X2 - 7.0*SIN(X2) AT 76
0030 !F3 = X3*X3*X3*X3 - X3*X3*X3 + X3*X3 - 20.0*X3 - 7.0*SIN(X3) AT 76
0031 F2 = SIN(X2*X2)*X2 + SQRT(X2) AT 76
00000076(51/7/69) dfld X2
00000079(52/7/69) fsqrt
0000007b(53/9/118) dfld X2
0000007e(54/9/118) fmul fr0,fr0
00000080(55/8/63) fsin
00000082(56/7/119) dfmul X2
00000085(57/6/120) faddp fr1,fr0
00000087(58/5/57) dfstp F2
0032 F3 = SIN(X3*X3)*X3 + SQRT(X3) AT 8a
0000008a(60/7/90) dfld X3
0000008d(61/7/90) fsqrt
0000008f(62/9/121) dfld X3
00000092(63/9/121) fmul fr0,fr0
00000094(64/8/84) fsin
00000096(65/7/122) dfmul X3
00000099(66/6/123) faddp fr1,fr0
0000009b(67/5/78) dfstp F3
0033 QUAD = QUAD + (F1 + 4*F2 + F3) AT 9e
0000009e(69/8/124) dfld F2
000000a1(70/8/124) dfmul 4.0_2
000000a7(71/7/125) dfadd F3
000000aa(72/7/125) dfadd F1
000000ad(73/6/126) dfadd (RESULT of QUAD)
000000b0(74/5/98) dfstp (RESULT of QUAD)

anonymous
()
Ответ на: комментарий от anonymous

0034 X1 = X3 AT b3
000000b3(76/5/100) dfld X3
000000b6(77/5/100) dfstp X1
0035 X2 = X1 + H2 AT b9
000000b9(79/6/127) dfld X1
000000bc(80/6/127) dfadd H2
000000bf(81/5/103) dfstp X2
0036 X3 = X1 + H AT c2
000000c2(83/5/128) dfld X1
000000c5(84/5/128) dfadd H
000000c8(85/4/106) dfstp X3
000000cb(87/3/49) Label __N4
000000cb(88/4/47) mov eax,address of B
000000ce(89/4/47) dfld [eax]
000000d0(90/4/47) dfld X3
000000d3(91/4/47) fcomip fr0,fr1
000000d5(92/4/47) fcomp fr0,fr0 ; Clean up the coprocessor stack
000000d7(93/4/47) jbe __N5
0037 ENDDO AT d9

anonymous
()
Ответ на: комментарий от anonymous

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

Что касается снижения производительности: я заметил, что ее снижение идет не при обычных операциях умножения/деления,а при вызове sin, sqrt...


Теперь пойдет ассемблер после gfortran-а

anonymous
()
Ответ на: комментарий от anonymous

.file "simpson.f95"
.text
.globl ___simpson__quad
.def ___simpson__quad; .scl 2; .type 32; .endef
___simpson__quad:
pushl %ebp
movl %esp, %ebp
subl $88, %esp
movl 12(%ebp), %eax
fldl (%eax)
movl 8(%ebp), %eax
fldl (%eax)
fsubrp %st, %st(1)
movl 16(%ebp), %eax
movl (%eax), %eax
pushl %eax
fildl (%esp)
leal 4(%esp), %esp
fdivrp %st, %st(1)
fstpl -32(%ebp)
fldl -32(%ebp)
fldl LC0
fdivrp %st, %st(1)
fstpl -40(%ebp)
movl 8(%ebp), %eax
fldl (%eax)
fstpl -24(%ebp)
fldl -24(%ebp)
faddl -40(%ebp)
fstpl -16(%ebp)
fldl -24(%ebp)
faddl -32(%ebp)
fstpl -8(%ebp)
fldz
fstpl -72(%ebp)
fldl -24(%ebp)
fmull -24(%ebp)
fstpl (%esp)
call _sin
fmull -24(%ebp)
fldl -24(%ebp)
fsqrt
faddp %st, %st(1)
fstpl -64(%ebp)
L2:
movl 12(%ebp), %eax
fldl (%eax)
fldl -8(%ebp)
fxch %st(1)
fucomip %st(1), %st
fstp %st(0)
setae %al
movzbl %al, %eax
xorl $1, %eax
testl %eax, %eax
jne L3
fldl -64(%ebp)
fstpl -48(%ebp)
fldl -16(%ebp)
fmull -16(%ebp)
fstpl (%esp)
call _sin
fmull -16(%ebp)
fldl -16(%ebp)
fsqrt
faddp %st, %st(1)
fstpl -56(%ebp)
fldl -8(%ebp)
fmull -8(%ebp)
fstpl (%esp)
call _sin
fmull -8(%ebp)
fldl -8(%ebp)
fsqrt
faddp %st, %st(1)
fstpl -64(%ebp)
fldl -56(%ebp)
fldl LC2
fmulp %st, %st(1)
faddl -48(%ebp)
faddl -64(%ebp)
fldl -72(%ebp)
faddp %st, %st(1)
fstpl -72(%ebp)
fldl -8(%ebp)
fstpl -24(%ebp)
fldl -24(%ebp)
faddl -40(%ebp)
fstpl -16(%ebp)
fldl -24(%ebp)
faddl -32(%ebp)
fstpl -8(%ebp)
jmp L2
L3:
fldl -72(%ebp)
fldl LC3
fdivrp %st, %st(1)
fmull -32(%ebp)
fstpl -72(%ebp)
fldl -72(%ebp)
leave
ret
.section .rdata,"dr"
.align 8
LC0:
.long 0
.long 1073741824
.align 8
LC2:
.long 0
.long 1074790400
.align 8
LC3:
.long 0
.long 1075314688
.def _sin; .scl 2; .type 32; .endef

anonymous
()
Ответ на: комментарий от anonymous

Вот тут вместо fsin после FTN-овского компилятора выдается некий _sin который я не очень уже понимаю. (это было для REAL(8))

Теперь для REAL(4):

anonymous
()
Ответ на: комментарий от anonymous

.file "simpson.f95"
.text
.globl ___simpson__quad
.def ___simpson__quad; .scl 2; .type 32; .endef
___simpson__quad:
pushl %ebp
movl %esp, %ebp
subl $56, %esp
movl 12(%ebp), %eax
flds (%eax)
movl 8(%ebp), %eax
flds (%eax)
fsubrp %st, %st(1)
movl 16(%ebp), %eax
movl (%eax), %eax
pushl %eax
fildl (%esp)
leal 4(%esp), %esp
fdivrp %st, %st(1)
fstps -16(%ebp)
flds -16(%ebp)
flds LC0
fdivrp %st, %st(1)
fstps -20(%ebp)
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, -12(%ebp)
flds -12(%ebp)
fadds -20(%ebp)
fstps -8(%ebp)
flds -12(%ebp)
fadds -16(%ebp)
fstps -4(%ebp)
movl $0x00000000, %eax
movl %eax, -36(%ebp)
flds -12(%ebp)
fmuls -12(%ebp)
fstps (%esp)
call _sinf
fmuls -12(%ebp)
flds -12(%ebp)
fsqrt
faddp %st, %st(1)
fstps -32(%ebp)
L2:
movl 12(%ebp), %eax
flds (%eax)
flds -4(%ebp)
fxch %st(1)
fucomip %st(1), %st
fstp %st(0)
setae %al
movzbl %al, %eax
xorl $1, %eax
testl %eax, %eax
jne L3
movl -32(%ebp), %eax
movl %eax, -24(%ebp)
flds -8(%ebp)
fmuls -8(%ebp)
fstps (%esp)
call _sinf
fmuls -8(%ebp)
flds -8(%ebp)
fsqrt
faddp %st, %st(1)
fstps -28(%ebp)
flds -4(%ebp)
fmuls -4(%ebp)
fstps (%esp)
call _sinf
fmuls -4(%ebp)
flds -4(%ebp)
fsqrt
faddp %st, %st(1)
fstps -32(%ebp)
flds -28(%ebp)
flds LC2
fmulp %st, %st(1)
fadds -24(%ebp)
fadds -32(%ebp)
flds -36(%ebp)
faddp %st, %st(1)
fstps -36(%ebp)
movl -4(%ebp), %eax
movl %eax, -12(%ebp)
flds -12(%ebp)
fadds -20(%ebp)
fstps -8(%ebp)
flds -12(%ebp)
fadds -16(%ebp)
fstps -4(%ebp)
jmp L2
L3:
flds -36(%ebp)
flds LC3
fdivrp %st, %st(1)
fmuls -16(%ebp)
fstps -36(%ebp)
movl -36(%ebp), %eax
movl %eax, -52(%ebp)
flds -52(%ebp)
leave
ret
.section .rdata,"dr"
.align 4
LC0:
.long 1073741824
.align 4
LC2:
.long 1082130432
.align 4
LC3:
.long 1086324736
.def _sinf; .scl 2; .type 32; .endef

anonymous
()
Ответ на: комментарий от anonymous

а тут уже используется некий _sinf

anonymous
()
Ответ на: комментарий от anonymous

_sin и _sinf - это библиотечные функции синуса для двойной и одинарной точности соответственно. У меня они изгоняются (и вместо них используется команда fsin) при опциях -O2 -ffast-math как в gcc так и в g77. gfortrana у меня нет. А так остальной код вроде во всех случаях адекватный. Попробуй скомпилировать с -O2 -ffast-math, будет ли время работы сильно отличаться?

anonymous
()
Ответ на: комментарий от anonymous

ДА!!! Оно!!! причем комбинация должна быть именно такой. Спасибо! Даже не представляете, сколько мне денег сэкономили! Как вернусь обратно в Россию, с меня ящик пива.

anonymous
()
Ответ на: комментарий от anonymous

Так как мекня тоже волнует обсуждаемый здесь вопрос, то хотелось бы уточнить. Ассемблер знал только в рамках некоторго введения в универе.

_sin и _sinf - это функции написанные разработчиками компилятора?

fsin - это команда процессора (такая же как mov, add и т.д.) для вычисления синуса?

Если это так то я вообще не понимаю смысл использования библиотечных функций которые самостоятельно рассчитывают синус, а не используют возможности процессора. Это же будет заведомо медленней. Почему эта опция не включена по умолчанию?

anonymous
()
Ответ на: комментарий от anonymous

Потому что у процессоров бывают некоторые погрешности в вычислениях. А компилятор себе и своим библиотекам доверяет больше, чем сопроцессору.

svu ★★★★★
()
Ответ на: комментарий от svu

>Потому что у процессоров бывают некоторые погрешности в вычислениях. А компилятор себе и своим библиотекам доверяет больше, чем сопроцессору.

У меня есть еще одна версия (правда, не знаю, на сколько соответствующая истине): компилятор сей может выдавать код для жуть как старых процессоров, у которых команды fsin могло и не быть.

anonymous
()
Ответ на: комментарий от anonymous

>У меня есть еще одна версия (правда, не знаю, на сколько соответствующая истине): компилятор сей может выдавать код для жуть как старых процессоров, у которых команды fsin могло и не быть.

Это вряд ли. Если было так, то использование команды fsin включалось бы при указании архитектуры процессора.

В любом случае это странно. Фортран применяется исключительно для решения выислительных задач. Причем зачастую решение задачи занимает несколько часов а то и суток. В отдельных случаях счет идет на недели и месяцы. И использование по умолчанию самописных библиотечных функций вместо возможностей процессора явно необоснованно.

anonymous
()
Ответ на: комментарий от anonymous

> И использование по умолчанию самописных библиотечных функций вместо возможностей процессора явно необоснованно.

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

anonymous
()
Ответ на: комментарий от anonymous

>Ну, ээ. IIRC, во многих процессорах тригонометрия считается с неполной точностью. Тебе как болше нравится - ждать неделю правильного результата, или получить за день неизвестно какой?

Ну ладно. Спорить не буду. По своему небольшому опыту могу сказать что код генерируемый CVF и IFC проводит вычсления с достаточной точностью. Насколько я понимаю там по умолчанию по возможности используются команды процессора.

anonymous
()
Ответ на: комментарий от anonymous

Не знаю какие причины для этого в компиляторе gfortran (может быть, потому что backend у них с С компилятором общий), но в С для этого есть причины --- sin это все-таки функция, а не встроенный оператор языка, поэтому если компиляция производится без всяких оптимизаций, то естественно обрабатывать sin именно как функцию, а не использовать для этого команды процессора. В принципе я могу определить свою функцию sin, которая к синусу никакого отношения не имеет. Насколько я понимаю, в стандарте поведение компилятора в данном случае не оговорено, но я думаю что генерация неоптимизированного кода по умолчанию (без всяких опций) --- это правильно.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.