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

Unexpected stack overflow: array temporaries?

Arjen_Markus
Honored Contributor II
1,512 Views

I encountered a peculiar problem with a small program - for a case with large arrays the program crashed because of stack space problems. It was solved by adding the option -heap-arrays, but as the program merely uses pointers to array sections I was surprised that temporary arrays were involved.

Is there a way to get the compiler to show where these are created? 

I have attached the program source and the input file (rename it to .inp).

Further information: I also have a version that uses ASSOCIATE instead of pointers and it gives the same problem. With the same solution. It is part of a series of programs to explore what variations are possible. 

0 Kudos
15 Replies
andrew_4619
Honored Contributor III
1,450 Views

I recall the optimiser reports show some detail on temp creation but that is a while since I looked at that,

0 Kudos
garraleta_fortran
1,424 Views

do this

0 Kudos
Arjen_Markus
Honored Contributor II
1,419 Views

I did use that option to get around the problem, but the question is: why would that be necessary? What temporary arrays are used? 

0 Kudos
JohnNichols
Valued Contributor III
1,350 Views

using stock standard console1 Fortran copy your code in no changes in VS 2025 Preview oneapi 2025.1 using ifx in debug mode, compiles fine.  

Need input file to test it.  

0 Kudos
JohnNichols
Valued Contributor III
1,350 Views

using your exact code.  NO tweaking 

0 Kudos
Arjen_Markus
Honored Contributor II
1,333 Views

I supplied a sample input file as "poisson_island_pointer.txt" since the forum does not accept files with ".inp" as the extension. The matrix size 1000x1000 causes the stack overflow, both with the debug (-Od) and the optimised version (-O2). My current compiler version is 2025.0.0, perhaps I should upgrade :).

0 Kudos
garraleta_fortran
1,274 Views

I have successfully received the INP file.
This is the result of the process.

0 Kudos
Arjen_Markus
Honored Contributor II
1,166 Views

So, you succeeded in running the program. Unfortunately, I removed a part of the program that resides in another source file, so that you did not get the compiler information. What compiler and compile options did you use? 

0 Kudos
garraleta_fortran
1,160 Views
0 Kudos
Arjen_Markus
Honored Contributor II
1,151 Views

Ah, yes, of course, that will solve it :). See also Ron Green's detailed answer. 

That said, it helps (me) to read such explanations as I am not a compiler writer or very knowledgeable about them (beyond having used them a lot over the years :)). 

0 Kudos
Ron_Green
Moderator
1,248 Views

it's interesting that you posted this question at this time.  Not 2 weeks ago we started discussions about the capability to alert when array temps are used.  Several customers have recently asked for such a new feature.

There are 2 possibilities to this feature request:  

One is a compile time check, perhaps a new -warn keyword to issue a compile time warning for array temp need.  The trouble here is that sometimes the array temp is only determined to be needed at runtime.  So the compiler warning would have to be something like "array temporary creation possible <here>".  Other cases are certain "array temporary creation <here>".  

Another possibility for this feature request is runtime checking.  Perhaps something under the -check <keyword> option.  This would be more exact, as the warning would emit only when array temp creation is encountered.    This could cause a WHOLE LOT of warnings if the creation occurs countless times in a run.  Which is quite possible, it could be millions of such occurences.  Runtime checks are sent to STDERR so in theory one could redirect STDERR to a file so as not to clutter the actual runtime output stream in STDOUT.  Still, I would not like to filter millions of lines of warnings to find all the locations of array temp usage. 

 

Of the 2 solutions proposed, I prefer the compile time check.  I think a runtime check would just flood the user with too much output to be practical.  What do you think? 

 

As you found, the -heap-arrays option can help avoid the default stack allocation for array temps.  This could be added to your ifx.cfg file to apply to all compilations if you so desire.   We have been asked "why not make some stack/heap threshold default"?  The answer - performance.  Stack allocation is much faster than tracking things in heap.  So if we changed the compiler to auto detect large array temps and automatically do those in heap then performance would be impacted.  And I think you will agree that this would cause an uproar.  

 

I will resume the discussion of a possible new -warn feature to flag possible array temp 

 

Now in your particular example it is quite obvious to people familiar with Fortran compiler so spot your array temp need.  It is this 

pderiv = diffw * pwest  + &
                 diffe * peast  + &
                 diffn * pnorth + &
                 diffs * psouth   &
                 - (diffw + diffe + diffn + diffs) * pcentre + pforce
real, dimension(:,:), pointer             :: pcentre, pwest, peast, pnorth, psouth, pforce, pderiv, &
                                                 diffw, diffe, diffn,  diffs

look at the left-hand side of the assignment and the right-hand side:  pderiv is a pointer to real, dimension(:,:)  targets.  Just like the LHS.  So pderiv COULD possibly alias the same memory as any of the pointers on the RHS.  Sure, YOU can see that it doesn't but the compiler is not aware of how you have assigned the pointers and thus makes the safe assumption to make an array temp for the RHS calculation then store the results with a mem move into the data pointed to by pderiv.  Compilers err on the side of safety. 

Arjen_Markus
Honored Contributor II
1,159 Views

Ah, thanks for your enlightening answer! In more detail:

  • I agree that a compile-time check on the creation of temporary arrays is more useful. The loop in my small test program would probably become more involved and I am thinking of transferring the inner part to a subroutine, so that more customisation is possible, Like I said: this is an investigation into the possibilities.
  • Such a check is useful as a prognosis tool. In my case, the program stops immediately, but it might also occur after several hours of hard labour (by the computer) when it enters the output phase of the program :).
  • The stack overflow also occurred in the version that uses association in stead of pointers. I would assume that the compiler is then capable of detecting that pderiv is not aliased to anything involving the right-hand side. There the code looks like this:

    !
    ! Set up the associations to the respective array sections
    !
    associate(                             &
        pcentre => u(2:nx+1,2:ny+1),       &
        pwest   => u(1:nx  ,2:ny+1),       &
        peast   => u(3:nx+2,2:ny+1),       &
        psouth  => u(2:nx+1,1:ny  ),       &
        pnorth  => u(2:nx+1,3:ny+2),       &
        pforce  => force(2:nx+1,2:ny+1),   &
        pderiv  => du(2:nx+1,2:ny+1),      &
        diffw   => diffx(1:nx,2:ny+1),     &
        diffe   => diffx(2:nx+1,2:ny+1),   &
        diffn   => diffy(2:nx+1,2:ny+1),   &
        diffs   => diffy(2:nx+1,1:ny)      )

        do while ( error > eps .and. iter < max_iter )

            pderiv = diffw * pwest  + &
                     diffe * peast  + &
                     diffn * pnorth + &
                     diffs * psouth   &
                     - (diffw + diffe + diffn + diffs) * pcentre + pforce

            iter  = iter + 1
            error = deltt * sum(abs(du)) / (nx-2) / (ny-2)

            u = u + deltt * du

            write(  *, * ) iter, error
            write( 20, * ) iter, error
        enddo

    end associate

​
  • I found that gfortran handles this differently and actually of the four versions of the program the "associate" version is faster.
0 Kudos
Arjen_Markus
Honored Contributor II
1,120 Views

Actually, knowing the reason for the compiler to create such a temporary array, I now see some more variations :). They might be able to persuade the compiler not to do this, thus probably enhancing the performance.

0 Kudos
jimdempseyatthecove
Honored Contributor III
729 Views

>>This could cause a WHOLE LOT of warnings...

In my experience with ifort, the warning appeared once for any statement. iow by use of a once-only flag for each allocation.

 

Jim Dempsey

0 Kudos
Ron_Green
Moderator
858 Views

Feature Request ID is CMPLRLLVM-68444


0 Kudos
Reply