-O2 vs. explicit optimization options

-O2 vs. explicit optimization options

Hello all,

I running into a problem where I get floating point exceptions when my code is compiled -O1, -O2, or -O3 but it works in -g or -O0 mode. I believe there are some optimization associated with floating point operations that is causing my problem. I would like to gradually activated all the optimizations evident in -O# manually to determine which one causes the FPE and just turn that one off.

My question is whether this is even possible.

So far I've tried -O2 -fp-speculation=off -no-fp-port -fp-model precise -fp-stack-check -fpconstant and I still get the same FPE.

Thanks in advance

John

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

John,

Try the following in this order

1) Compile in debug mode, enable runtime checks for uninitialized variables and subscript out of bounds check
2) Compile with gen-interfaces and warn:interfaces
3) Use IMPLICIT NONE

If the above does not locate the error in the code then, depending on what you use for compiling your application, do what you suggested yourself:

Compile some files with O0 and others with O3. You could start with allO0 andgradually add one at a time. If your project has 100's of files then do a binary search like method 1st half, if that works, next quarter, etc... You should be able to quickly isolate the errant code. I've done this on a (Windows) Fortran solution with ~750 source files and in about 10 builds I had the file of interest.

Jim Dempsey

www.quickthreadprogramming.com

Quoting - jimdempseyatthecove

John,

Try the following in this order

1) Compile in debug mode, enable runtime checks for uninitialized variables and subscript out of bounds check
2) Compile with gen-interfaces and warn:interfaces
3) Use IMPLICIT NONE

If the above does not locate the error in the code then, depending on what you use for compiling your application, do what you suggested yourself:

Compile some files with O0 and others with O3. You could start with allO0 andgradually add one at a time. If your project has 100's of files then do a binary search like method 1st half, if that works, next quarter, etc... You should be able to quickly isolate the errant code. I've done this on a (Windows) Fortran solution with ~750 source files and in about 10 builds I had the file of interest.

Jim Dempsey

Thanks for the reply. I have a sneaking suspicion that it might be uninitialized variables. Problem is that this code has a lot of legacy Fortran 77. It will be worth going through though and fixing.

I'll post my progress.

And I'll add a comment that is probably obvious (I do this a lot):

-g is not mutually exclusive with the -Ox options. If you use -g and do not use other -O options, you get O0. If you use:
-g -O2 you will get O2 optimizations with symbolic information.

This is useful along with the -traceback option:

-g -O2 -traceback

to isolate where the FPE is occurring. Perhaps you already know. And of course, the FPE that brings down the app is often the result of some other error much earlier in the application.

You might also add to this:

-g -O2 -traceback -fpe0

to try to trap all FP exceptions - perhaps it will find something earlier on in the app.

ron

Another usefull tool is valgrind: http://valgrind.org/

Ricardo Reis
'Non Serviam'
@ http://www.lasef.ist.utl.pt
@ http://www.radiozero.pt
@ http://rreis.tumblr.com
@ http://www.flickr.com/photos/rreis

Not enough information has been given to know whetherthis isrelevant: -O0 has implied x87 code, at least up through compiler 10.1. In the 64-bit (and 11.0 32-bit) compilers, anything other than -O0 (either explicit, or set by -g with no over-ride) set SSE2 as a default (unless you set -mp). So, the numerical ranges of intermediate results are entirely different.
If you wanted SSE2 code with full standards compliance, you would set -fp-model precise (or source, they should be the same). That also could affect production of exceptions.

Quoting - tim18

Not enough information has been given to know whetherthis isrelevant: -O0 has implied x87 code, at least up through compiler 10.1. In the 64-bit (and 11.0 32-bit) compilers, anything other than -O0 (either explicit, or set by -g with no over-ride) set SSE2 as a default (unless you set -mp). So, the numerical ranges of intermediate results are entirely different.
If you wanted SSE2 code with full standards compliance, you would set -fp-model precise (or source, they should be the same). That also could affect production of exceptions.

GRRRR.

This is what I hate about any compiler. There are a ton of options, many of them CPU specific, with millions of combinations. I doubt even 10% of the general user population even know what half of the options do. How hard is it to specify all optimizations set/unset when using -g, -O0, -O2, -O3, etc?

I've now run into the same problem (or another problem, can't tell) on a different application. I've narrowed some floating point differences to a routine but have not been able to come up with the options necessary to make the floating point calculations produce the same results. Can anyone tell me how I can make the FP calculations for -O2 match what is done for -g -O0? I've tried '-O2 -fp-speculation=off -fp-model precise' and I get the same answer as '-O2' which is different from '-g -O0'.

Any suggestions welcome: I'm using ifort 11.0 20081105 on 64bit Intel Core 2 Quad proc but running on a system with dual qaud Core 2 64bit Intel Zeon chips.

Thanks in advance

John

If your -O0 (non-SSE) results are more correct, likely possibilities are (as already mentioned) that you require initialization or SAVE, or that you are depending on extended (or at least, promotion of expressions to double) precision. There is a -save option which attempts to give the effect of SAVE, and a -zero option which will initialize certain static data to zero. Those aren't really meant to substitute for correcting the source code.

Quoting - Ronald Green (Intel)
And I'll add a comment that is probably obvious (I do this a lot):

-g is not mutually exclusive with the -Ox options. If you use -g and do not use other -O options, you get O0. If you use:
-g -O2 you will get O2 optimizations with symbolic information.

This is useful along with the -traceback option:

-g -O2 -traceback

to isolate where the FPE is occurring. Perhaps you already know. And of course, the FPE that brings down the app is often the result of some other error much earlier in the application.

You might also add to this:

-g -O2 -traceback -fpe0

to try to trap all FP exceptions - perhaps it will find something earlier on in the app.

ron

Thanks for the advice. I was able to track down the error using this method but I think I was just lucky. When I compile with strict '-O2' option, I would get a crash about 150 iterations into the problem. With '-g -O2', the crash occured roughly 350 iterations. So the '-g' option is introducing some type of floating point modifications which over-ride the general '-O2' optimizations. My question is still whether anyone knows exactly what these differences are?

Thanks

John

-g does not really change optimizations but does add debug information and can cause data layout to change. If your program is accessing outside array bounds or has argument type mismatches, rearranging the order of variables in memory could change behavior.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today