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

Stepping through code compiled with Optimizations on

John6
Beginner
1,290 Views

Recently I upgraded to the most recent version (2015) of the Intel Fortran compiler. After compiling up a Debug build, I noticed the Visual Studio (2010) debugger moving to unexpected code lines when F10 or F11 was pressed. Upon investigating, I determined that the Optimization setting for our Debug build was set to "Maximize Speed". If I change this setting to Disabled (/Od), the odd stepping behavior does not occur.

Now, the project I am using is under configuration control, and no settings were changed from the previous IVF compiler (2013.5.198). The Max Speed setting was the Debug default for that project and I had no issues stepping through the code using the Visual Studio debugger.

My question is: The default for our Debug build (from inherit from project defaults) seems to be Maximum Speed, which puzzles me because it is much more difficult to actually debug, because of the odd stepping behavior when pressing F10 or F11. Is Maximum Speed the default for Debug builds? And if so, Why? (I would have thought Disabled for Debug builds, and Maximize Speed for Release builds).

Also, if a Release is built with Maximize Speed, and a developer wants to actually debug it using Visual Studio, how can that be accomplished?

Note: I am aware that projects built with /Od and with Max Speed may result in different calculation results, depending on how the code was written.

0 Kudos
9 Replies
mecej4
Honored Contributor III
1,290 Views

One needs to distinguish between debugging at the machine level and debugging at the language level (C, Fortran, etc.). Now and then, we find that the compiler optimizer is introducing bugs, and we then have no escape from compiling with optimizations on and providing as much debugger support as possible. A different situation arises when one wishes to debug a program that runs without problems for a long time and then exhibits bugs. Here, one may wish to compile with optimizations enabled for the bug free routines, but disable optimizations for the part of the code that is suspect.

One of the VS options lets you specify if you want the debugger to fall through to assembler level debugging for code sections which do not have source level debugging support compiled in.

0 Kudos
John6
Beginner
1,290 Views

My post refers to debugging at the language level.

Would the optimization settings affect how code with arithmetic if statements is evaluated?

I am trying to narrow down where the calculations deviations occur, and the most likely spot is in a matrix inversion algorithm which uses arithmetic if statements, many loops, and a go to statement.

0 Kudos
mecej4
Honored Contributor III
1,290 Views

Would the optimization settings affect how code with arithmetic if statements is evaluated?

Quite likely. Optimizers are quite capable these days, and can make significant changes to the order of operations, including removing loops altogether. The Intel compiler has options to let you print optimization reports to help you see what it did.

The rules of the optimization game, as I see them: if the code is correct, the optimizer can apply any transformations that will not alter the semantics of the program. In such cases, you would have no need for line-by-line debugging.  If the code is not correct, however, the program may well produce different results and runtime behavior may be different with different levels of optimization.

Consider this brief example:

   dimension x(3)

   i=0

   if (i .gt. 0 .and. x(i) .lt. 0.001) then

...

Compiled without optimization, this program may abort with an access violation; if subscript checking has been enabled, the reference to x(0) would be flagged at runtime. Next, suppose optimization is requested.The optimizer can recognize that the entire IF...ENDIF block will not be executed, and eliminate all the statements in the block. The program is, technically, in error, but the effects of the error are benign and so the bug may go unnoticed for a long time.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,290 Views

Often when you need to debug optimized code you may need to insert asserts. And/or insert a function call to something benign. The line number on which the call is made is most often breakable. I.e. you can place a break point on it. This will affect the performance a bit and alter to a little extent the optimization, but it often leads to finding the problem in your code.

John, if you are not aware of it, the statement if (i .gt. 0 .and. x(i) .lt. 0.001) then as mentioned by mecej4 may be a little perplexing to C programmers. In that statement Fortran is free to compute either side the .and. as well as both at the same time. Therefore, expect at some time x(0) or x(-n) to be possible to be executed. C will shortcut left to right, Fortran is not assured to do that.

Jim Dempsey

0 Kudos
John6
Beginner
1,290 Views

Thanks, I have not used asserts before in Fortran code. Would you mind showing a simple example?

0 Kudos
John6
Beginner
1,290 Views

Sorry about the duplicate thread, had a little trouble yesterday getting the original to post.

I still do not see why the default optimization setting for a Debug build would be Optimize for Maximum Speed.

If the debugger is going to jump around because of this optimization setting, wouldn't it make more sense for the default setting to be optimizations Disabled? I can see why a Release build default setting would be maximum speed, no problem with that.

I spent much time today examining my program and it looks like the matrix inversion algorithm which is used will give different answers depending on whether the compiler is using /Od or maximum speed. Pretty frustrating, because the development is using Debug (/Od) and the Release uses max speed. Test case results for debug builds would then not match release build results.

(Also, I do not think this is a new issue specific to the 2015 compiler)

0 Kudos
IanH
Honored Contributor III
1,290 Views

Note the default setting for a debug build isn't maximise speed (the default is to disable optimisation) - that "maximise speed" setting has come in from somewhere else.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,290 Views

One way:

subroutine DebugThis()
write(*,*) "DebugThis" ! Place break point here
end subroutine DebugThis
...

IF(.NOT.(yourTestExpressionHere)) call DebugThis()

If you use the Fortran Preprocessor, you can globally define a macro

#define __ASSERT(x) IF(.NOT.(x)) call DebugThis()

...

__ASSERT((yourTestExpressionHere)) ! Note extra set of ()'s

I haven't tried the macro, so I cannot say if it will work properly with Fortran's logical expressions.

Also, if you use FPP, but not use the macro due to difficulties, it does support __LINE__ and __FILE__

IOW use call DebugThis(__FILE__, __LINE__), with the appropriately modified subroutine to take the args and display the location of the assert fail.

When you hit the break point, step out of the subroutine to the caller. Then look around as to the cause of the assert.

Jim

0 Kudos
John6
Beginner
1,290 Views

Thanks, IanH and Jim. The fact that my project default is wrong must be because it has come in from somewhere else (sigh).

I will try out the assert tomorrow, it looks like it should work.

0 Kudos
Reply