- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello everyone!
First the important things: Compiler IVF XE 12.0.2.154
My problem is as follows:
During an iteration I have to compare an intermediate result of that iteration to a value calculated prior to the iteration. Both values are defined as REAL and the default REAL kind of the compiler is set to 4 Bytes.
IF (Y .LE. ASBS) THEN ...
Y ... intermediate result
ASBS ... value calculated prior to the iteration
Everything works fine, until the REAL value of Y is equal to the REAL value of ASBS. In this case the program should execute the statements in the if-block, but instead of doing so simply skips the block. (See the pictures attached)
A more thorough examination of the two values, using them both declared as DOUBLE PRECISION, reveals that indeed ASBS is a little smaller than Y.
To make sure this was no display problem of the debugger I printed out both results on the screen as well, but the output showed the same values as were displayed by the debugger.
My question now is: Why does the compiler behave like that and how can I change that behaviour?
Many thanks in advance.
First the important things: Compiler IVF XE 12.0.2.154
My problem is as follows:
During an iteration I have to compare an intermediate result of that iteration to a value calculated prior to the iteration. Both values are defined as REAL and the default REAL kind of the compiler is set to 4 Bytes.
IF (Y .LE. ASBS) THEN ...
Y ... intermediate result
ASBS ... value calculated prior to the iteration
Everything works fine, until the REAL value of Y is equal to the REAL value of ASBS. In this case the program should execute the statements in the if-block, but instead of doing so simply skips the block. (See the pictures attached)
A more thorough examination of the two values, using them both declared as DOUBLE PRECISION, reveals that indeed ASBS is a little smaller than Y.
To make sure this was no display problem of the debugger I printed out both results on the screen as well, but the output showed the same values as were displayed by the debugger.
My question now is: Why does the compiler behave like that and how can I change that behaviour?
Many thanks in advance.
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is not the compiler behavior that needs to change; it is your expectation of how floating point arithmetic should operate.
You are comparing two REAL*4 variables, whose decimal representations as shown in the debugger agree to seven significant digits. However, if you looked at their internal representations, it is possible that you would have found one of them to be Z'40F78FF7' and the other Z'40F78FF8'; although the difference between these numbers cannot be seen with seven significant decimal digits, there is a difference. A test of equality must fail unless all bits match (32 bits for REAL*4, 64 for REAL*8, etc.)
You need to alter your program so that your comparisons for equality between floating point values are more realistic. This is a topic that is well covered in textbooks. Many compilers routinely issue warning messages when they encounter comparisons for equality (.EQ., .LE., .GE.) between floating point numbers.
You are comparing two REAL*4 variables, whose decimal representations as shown in the debugger agree to seven significant digits. However, if you looked at their internal representations, it is possible that you would have found one of them to be Z'40F78FF7' and the other Z'40F78FF8'; although the difference between these numbers cannot be seen with seven significant decimal digits, there is a difference. A test of equality must fail unless all bits match (32 bits for REAL*4, 64 for REAL*8, etc.)
You need to alter your program so that your comparisons for equality between floating point values are more realistic. This is a topic that is well covered in textbooks. Many compilers routinely issue warning messages when they encounter comparisons for equality (.EQ., .LE., .GE.) between floating point numbers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, you should use
TOL=1.0e-07 ! or some reasonable value for REAL*4 numbers
IF(abs(Y-ASBS).LE.TOL) then
TOL=1.0e-07 ! or some reasonable value for REAL*4 numbers
IF(abs(Y-ASBS).LE.TOL) then
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can also use the functions epsilon(), nearest() or rrspacing()to find a number that
is very close but still different.
A more sophisticated method is to use a fuzzy comparison method - see http://ftp.cac.psu.edu/pub/ger/fortran/hdk/eps.f90
Regards,
Arjen
is very close but still different.
A more sophisticated method is to use a fuzzy comparison method - see http://ftp.cac.psu.edu/pub/ger/fortran/hdk/eps.f90
Regards,
Arjen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your kind reminder on the issue of floating point arithmetics. I was aware of that problem in general, but didnt think it was an issue here.
I did some research on my problem and found the core of it to be some place different.
The code I work on is some research code originally created in the 90s using CVF 6. Of course the code was updated when new research results had been available, but the compiler stayed the same.
Now weve reached a point at which it is impossible to use the CVF 6 any longer, because of the introduction of Fortran 2003 features, which are not supported by CVF 6.
So we migrated from CVF 6 to IVF 11. Everything looked fine in the first place, but now as more and more special test-cases are created, there are some differences in the output.
Some test-cases work fine, when using the CVF-compiled version, but fail when the IVF-compiled version is used. I also did the changes suggested by Steve Lionel in his migration-paper (Floating Point Model -> source, Enable Enhanced Instruction Set -> No enhanced instruction set), which made the results slightly worse. The variation in the result is up to 100 %, which is not acceptable.
I've also searched the board for similar problems and found this related topic:
http://software.intel.com/en-us/forums/showthread.php?t=66793&o=d&s=lr&wapkw=%28%2Bfortran+openmp%29
What I could not figure out is whether the "X87"-Instruction-Set (CVF 6) is the same as the "IA-32"-Instruction-Set (IVF 11), or just similar to it.
From my experience I would say they are just similar, so my question is:
Is there any way to make the IVF 11 use the "X87"-Instruction-Set?
I did some research on my problem and found the core of it to be some place different.
The code I work on is some research code originally created in the 90s using CVF 6. Of course the code was updated when new research results had been available, but the compiler stayed the same.
Now weve reached a point at which it is impossible to use the CVF 6 any longer, because of the introduction of Fortran 2003 features, which are not supported by CVF 6.
So we migrated from CVF 6 to IVF 11. Everything looked fine in the first place, but now as more and more special test-cases are created, there are some differences in the output.
Some test-cases work fine, when using the CVF-compiled version, but fail when the IVF-compiled version is used. I also did the changes suggested by Steve Lionel in his migration-paper (Floating Point Model -> source, Enable Enhanced Instruction Set -> No enhanced instruction set), which made the results slightly worse. The variation in the result is up to 100 %, which is not acceptable.
I've also searched the board for similar problems and found this related topic:
http://software.intel.com/en-us/forums/showthread.php?t=66793&o=d&s=lr&wapkw=%28%2Bfortran+openmp%29
What I could not figure out is whether the "X87"-Instruction-Set (CVF 6) is the same as the "IA-32"-Instruction-Set (IVF 11), or just similar to it.
From my experience I would say they are just similar, so my question is:
Is there any way to make the IVF 11 use the "X87"-Instruction-Set?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>The variation in the result is up to 100 %, which is not acceptable.
That is an indication of the presence of bugs in the code, which need to be removed. Such bugs often come alive only with one compiler or the other, but their detection should trigger a search-and-destroy mission, not a search for compiler options to hide them -- in other words, sweep-under-the-rug options.
IA32 refers to the instruction set that debuted on the 386 chip, which did not have a built in FPU. Later chips such as the 486DX, Pentium, etc., had a built in FPU, and the term IA32 is sometimes used to include x87 instructions as well. You can ask the IFort 11.1 compiler to produce X87 instructions for real arithmetic using the /architecture:IA32 option; however, as I stated above, this should be regarded as a stop-gap measure.
That is an indication of the presence of bugs in the code, which need to be removed. Such bugs often come alive only with one compiler or the other, but their detection should trigger a search-and-destroy mission, not a search for compiler options to hide them -- in other words, sweep-under-the-rug options.
IA32 refers to the instruction set that debuted on the 386 chip, which did not have a built in FPU. Later chips such as the 486DX, Pentium, etc., had a built in FPU, and the term IA32 is sometimes used to include x87 instructions as well. You can ask the IFort 11.1 compiler to produce X87 instructions for real arithmetic using the /architecture:IA32 option; however, as I stated above, this should be regarded as a stop-gap measure.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Unless you used the fltconsistency option with CVF, and similar options such as /arch:IA32 /fp:source, with ifort, you could expect difficulty in matching numerics. I agree with mecej4 that the x87 selection to attempt automatic promotion of single precision expressions to double has to be considered a stop-gap. If your application depends on mixed single and double precision, you should write it into the source code explicitly. No compiler could apply the implicit promotions with full consistency; ifort might find more of them than CVF did.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page