Hi, I’m working on a big legacy code written in FORTRAN.
When I compile this code with gfortran the results are different from the same code compiled with pgf90.
The problem is the evaluation of mathematical expressions. The two compilers evaluate the order of operands in different ways. I’m compiling with the flags -g and -O0. I thought that disabling the optimizations the order of evaluation was the same, but this isn’t true.
Do you know a way to impose the same order? Obviously, I can rewrite the expressions using the parenthesis, but this project is very big.
Alberto Riccardo Martinelli
Hi Alberto Riccardo Martinelli,
Do you know a way to impose the same order?
No, not that I know of.
Though are you sure it’s order of operations? Fortran defines the order of operations and only has some room for differences with associativity. Do you have an example?
-Mat
yes this is the example:
PROGRAM PRECISION
REAL UNMOIX, UNMOIY
REAL F00, F01, F10, F11, Y, Z,X
X=0.5077457427978515625
UNMOIX = 0.4922542572021484375
UNMOIY = 0.50304734706878662109375
F00=268.10198974609375
F01=268.108001708984375
Y=0.4969526231288909912109375
F10=271.407989501953125
F11= 271.66900634765625
Z = UNMOIX * UNMOIY * F00
WRITE(6, ‘(A20, F60.40)’) 'RESULT: ', Z
END PROGRAM
commands used to compile (in the project):
pgf90 -g -O0 -Minfo=all -Minform=inform -Mnofma -Mfixed -Kieee -pc 64 your_file.f -o pgi_exec
gfortran -g -O0 -Wall -Wextra -fcheck=all -fbacktrace your_file.f -o gnu_exec
if you change the expression using the parenthesis you get the same result.
Great, thanks for the example. Yes, the order in which the associative operators are being evaluated is causing differences. Though, the problem also could be viewed as a precision and round-off error issue. Would setting the default kind of REAL to 8 be an acceptable solution?
When I promote REAL to REAL*8, the results are the same no matter the order of operations or the compiler.
% cat test.f
PROGRAM PRECISION
REAL UNMOIX, UNMOIY
REAL F00, F01, F10, F11, Y, Z,X
X=0.5077457427978515625
UNMOIX = 0.4922542572021484375
UNMOIY = 0.50304734706878662109375
F00=268.10198974609375
F01=268.108001708984375
Y=0.4969526231288909912109375
F10=271.407989501953125
F11= 271.66900634765625
Z = UNMOIX * UNMOIY * F00
* + UNMOIX * Y * F01
* + X * UNMOIY * F10
* + X * Y * F11
WRITE(6, '(A20, F60.40)') 'NoP RESULT: ', Z
Z = (((UNMOIX * UNMOIY) * F00)
* + (((UNMOIX * Y) * F01)
* + (((X * UNMOIY) * F10)
* + ((X * Y) * F11))))
WRITE(6, '(A20, F60.40)') 'RtL RESULT: ', Z
Z = (((((UNMOIX * UNMOIY) * F00)
* + ((UNMOIX * Y) * F01))
* + ((X * UNMOIY) * F10))
* + ((X * Y) * F11))
WRITE(6, '(A20, F60.40)') 'LtR RESULT: ', Z
END PROGRAM
% pgf90 -fast -Minfo test.f -o pgi_exec -r8; ./pgi_exec
NoP RESULT: 269.8479209231062441176618449389934539794922
RtL RESULT: 269.8479209231062441176618449389934539794922
LtR RESULT: 269.8479209231062441176618449389934539794922
% gfortran -O3 test.f -o gnu_exec -fdefault-real-8; ./gnu_exec
NoP RESULT: 269.8479209231062441176618449389934539794922
RtL RESULT: 269.8479209231062441176618449389934539794922
LtR RESULT: 269.8479209231062441176618449389934539794922
-Mat
When I promote REAL to REAL*8, the results are the same no matter the order of operations or the compiler.
Yes, but it doesn’t resolve the general problem.
I think there is no solution in the discrete world of computers.
Thanks for the help, Mat.
Alberto Riccardo Martinelli
Yes, but it doesn’t resolve the general problem.
Correct, but Fortran does not specify the order in which associative operation must be performed so the only way to guarantee order in your case would be to use parentheses.
-Mat