Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

NaN problem in Release version.

scitec
Beginner
416 Views

I have been investigating a problem in a numerical modeling program that gave markedly different results when run in debug mode than when run in release mode. I have finally traced it to a comparison involving a NaN value and produced the following sample code to illustrate the problem:

program NaNandOptimization

implicit none

! Variables

Real sngaValue(1)

Real sngNaN

Real sngSetup

! Body of NaNandOptimization

sngSetup = 0.0

sngNaN = sngSetup/sngSetup

sngaValue = 2.5

If (sngaValue(1) .EQ. sngNaN) Then

Write(*,*) sngNaN, sngaValue, ' are equal'

Else

Write(*,*) sngNaN, sngaValue, ' are not equal'

End If

Pause

end program NaNandOptimization

Depending upon whether it is compiled in debug mode or release mode, this program produces the following results.

Debug mode output:

NaN 2.500000 are not equal

Release mode output:

NaN 2.500000 are equal

My understanding is that .EQ. applied to NaN and any other number should always result in .False., even if the other number is the same NaN on the other side of the .EQ. If this is so, then the debug results are correct and not the release mode results.

Am I missing something basic here, or is there a problem with the compiler optimization?

For reference, I am using Intel Visual Fortran v9.1.038. The command lines used to produce this result are:

Debug mode:

Fortran command line:

/nologo /Zi /Od /module:"$(INTDIR)/" /object:"$(INTDIR)/" /traceback /check:bounds /libs:static /dbglibs /c

Linker command line:

/OUT:"Debug/NaN and Optimization.exe" /INCREMENTAL:NO /NOLOGO /DEBUG /PDB:"Debug/NaN and Optimization.pdb" /SUBSYSTEM:CONSOLE

Release mode:

Fortran command line:

/nologo /module:"$(INTDIR)/" /object:"$(INTDIR)/" /c

Linker command line:

/OUT:"Release/NaN and Optimization.exe" /INCREMENTAL:NO /NOLOGO /SUBSYSTEM:CONSOLE

Thanks for your comments.

Cheers,

Randy

0 Kudos
3 Replies
TimP
Honored Contributor III
416 Views
You have a better chance of avoiding optimizations which break NaN comparisons, if you add the option /fp:strict
However, if your intention is to detect a NaN, it is better to use an intrinsic provided by the compiler for that purpose. ifort does not yet implement the f2003 intrinsic, but it does have the ISNAN() intrinsic:
if(isnan(x))then
write(*,*)'NaN value'
else
....
0 Kudos
scitec
Beginner
416 Views

Hi, tim18,

Thanks for your reply. Yes, I'm confident setting /fp:strict will result in correct comparisons. (It was one of the tests I didwhile trying to track down the original problem after I discovered that it was optimization related.) However (as I understand it) this also can have a minorimpact on the accuracy of intermediate calculations, so I am reluctant to use it in this type of program (where iteration can cause minor variations to be amplified).

I have been able to work-around the immediate problem using IsNaN, but I now worry about other places in the code where similar problems might unexpectedly arise. Due to other constraints turning on divide-by-zero exceptions is not an option in this case. So the only indication of a problem is a deviation from the "correct" results, and unfortunately, the "correct" results are generally unknown to the user.

Perhaps the problem is fixed in version 10. Does anyone know?

Cheers,
Randy

0 Kudos
TimP
Honored Contributor III
416 Views
If you are depending on extra precision evaluation of intermediate results, such as you get by using the 32-bit compiler without SSE code generation, you can hardly expect thoroughly consistent results. You would have to find out where you need explicit promotion to double precision to make it more reliable. As most of us must support vectorization and 64-bit mode, where x87 code typically isn't available, this may be important in the long run.
I guess that /fp:precise would more often improve accuracy than degrade it, particularly since it would nearly always force the compiler to observe parentheses when evaluating expressions.
0 Kudos
Reply