I am struggling with a runtime segmentation fault error and hope that someone may provide useful insight on the issue. I have a code which runs fine with -O1 but crashes with -O2 and -O3 flags. If I add -ipo flag with -O3 or -O2 then the code runs fine again (although with -ipo flags I get some warning messages about unresolved subroutines). When I try to run the code in debugging mode with "-g -traceback -check bounds", it runs without any error, so I don not know what is causing the segmentation fault with -O3 optimization. Additionally, the code is running fine with gcc compiler with -03 flag on. I would greatly appreciate if someone could help me overcome the issue.
Thank you for pointing out the article. However, I do not seem to find any of the four causes to be relevant for my case (for example code crashes with -heap-arrays flag as well). It seems to me that intel compiler is doing loop unrolling but not inlining of the subroutines called within the loop. These subroutines are not thread safe since they try to update a global variable. Once I try the -ipo option the inlining of subroutines within the loop makes the code run (presumably by locking memory and making it thread-safe). Do you or anybody else think that it makes any sense and such a think can possibly happen?
IPO inlining will do nothing to correct race conditions. It may narrow the window of conflict but not eliminate it (unless by accident, not design). DO NOT assume that lack of observance of crash during simple test program assures correctness of your program...
Have you compiled your debug build with -warn interfaces? This will verify (to a great extent) that your calls match your arguments.
Make sure you are not referencing uninitialized variables (Fortran does not pre-initialize variables to any particular state).
You can compile -O2 and -O3 with -traceback (try without ipo first). While the line numbers might not be of use (due to compiler optimizations rearranging code), the procedure name should be valid. This may aid in narrowing down the problem.
Once you know the procedure name, you can insert tests to assert your assumptions.
You did not state as to if your program is linking in code from C/C++ (or other language). If so, the calling convention must be verified as well as argument checking.
Please be mindful that the Fortran standard requires that you not pass in arguments that alias one another. If they do, then that (those) procedures must be compiled with -assume dummy_aliases.
I have compiled with -warn all flag and the only warning I am getting is about unused variables.
-traceback with -O3 does not give me any additional information.
Again, the code has been compiled and used for production runs using GCC compliers (with -O3 flag), so if there was any trivial error in the coding it must have caused problem with gcc complier as well.
The only external library I am using is HDF5 (fortran version).
I should also add that the runtime segmentation fault occurs at varying and random time steps for the same code (compiled with -O3). -O3 -ipo have run properly in all the tests I have done so far.
Try -init=snan,arrays to check for uninitialized floating-point variables.
Increase the stack limit, e.g. ulimit -s unlimited for the bash shell. It's possible that different optimization levels (and compilers) might have different requirements for temporary arrays and stack storage. Also, inlining with -ipo might have reduced the need for temporaries or automatics.
Did -traceback (without -check or other extras) give you a traceback with source files, function names and line numbers?
Next step would be to provide your full command line. Better still, of course, if you can provide source code that would allow others to reproduce.
Have you figured out which source file needs to be compiled at -O1 to avoid the seg fault?
What exactly is the reason not to use global variables as loop bounds?
If a loop bound is a global variable, the compiler may have to assume that the value of the loop bound can change in ways not shown in the local routine (i.e., in the loop, the local routine calls an external function which changes the global variable).
By making the loop bound a local variable, the compiler can determine whether the loop bound will be changed or remain constant throughout the execution of the loop.
As Martyn says, local variables which are copies of routine arguments or global variables often allow the compiler to make optimizations it may not otherwise be able to make.