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

stack overflow on formated write

andrew_4619
Honored Contributor II
1,344 Views

The following lines are extracted from a subprogram to describe a problem. In this test case the plist integer array is 416520 long with 4 byte integers.  The write does not execute as it seems to want to create  a lot of stack space which causes a stack overflow. If I rewrite that write line with some logic and a do loop to write the data line by line then it works OK but is rather cludgy and there are quite a number of other locations in the code that could have the same issue with large model sizes. Is there some simple work around that could prevent the stack creation in this case? Is this expected behaviour of the compiler/runtime?

integer, intent(in) :: plist(:)
character(*), parameter :: G4 = '(A,6i8,:,/,*("        ",8i8,:,/))'
character(24):: G24
write(lu, G4,iostat=istat ) G24 ,plist

 

 

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
1,240 Views

If you passed a contiguous slice, the compiler is supposed to detect that and not make a copy.  Because the dummy argument is assumed-shape, no copy is normally needed. I'm wondering if your slice really was contiguous.

View solution in original post

10 Replies
jimdempseyatthecove
Honored Contributor III
1,330 Views

There are Linker options to specify the stack size.

With MS VS:

Executable Project | Linker | System | Stack Reserve Size (and Stack Commit Size)

The default under Windows (I think) is 2MB.

Your pre-formatted binary output is 1.6MB, the formatted data is about 4MB. As to what the Fortran runtime system will require, this is up to you to experiment. 

Note, this applies to the main thread only should your program be using OpenMP.

Jim Dempsey

0 Kudos
jdelia
New Contributor I
1,322 Views

I attach a test code based on your fragment that runs ok on Linux  with Fedora 37 with both ifort and ifx:

$ ifort --version
ifort (IFORT) 2021.9.0 20230302
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

$ ifort -warn all -O2 -o test186-ifort.exe test186.f90
$ test186-ifort.exe
begin test
end test
$ ifx --version
ifx (IFX) 2023.1.0 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

$ ifx -warn all -O2 -o test186-ifx.exe test186.f90
$ test186-ifx.exe
begin test
end test

 

module test_module
  implicit none
  public imprima
contains
  subroutine imprima (plist)
    integer, intent (in) :: plist(:)
    character (*), parameter :: g4 = '(a,6i8,:,/,*("        ",8i8,:,/))'
    integer      , parameter :: mm = 24
    character (mm) :: g24
    integer :: istat
    g24 (1:mm) = " "
    write (123, g4, iostat=istat) g24, plist
  end subroutine imprima
end module test_module
!
program main
  use test_module
  implicit none
  integer, parameter :: nn = 416520
  integer, allocatable :: plist (:)
  integer :: i
  write (*,*)" begin test"
  allocate (plist (nn))
  do i = 1, nn
     plist (i) = i
  end do
  call imprima (plist)
  deallocate (plist)
  write (*,*)" end test"
end program main

 

 

0 Kudos
andrew_4619
Honored Contributor II
1,301 Views

Yes Jim am aware that I can change the stack size but that is a bit of sledgehammer. I was surprised that the write seems to create  a significant additional additional stack  requirement.  @jdelia  thanks for looking at that, the problem is that the write is demanding additional stack on top of what is already being used in what is a large application. It was unfortunate that the plist array was in fact an passed array slice so a temp for that has already been created it seems.  I have experiment a little with this and just restructured that piece of code to avoid the issue but any insight as to what the run time is doing would be nice!

 

 

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,273 Views

The issue arises because the compiler doesn't know if plist is contiguous, so it creates a copy. Add the CONTIGUOUS attribute to the declaration of plist, make sure there's an explicit interface visible to the caller, and the stack copy disappears.

0 Kudos
andrew_4619
Honored Contributor II
1,252 Views

Thanks Steve that is a useful insight and I will keep that in mind in future. It didn't actually help in this case because I started with an allocatable 2D array which would be contiguous. I passed a 1D slice ( a column) which would also be contiguous, I assumed (wrongly) that a temp might have been created on passing but that was not the case it passed OK but had the stack overflow on the subsequent write. If I declared the slice as contiguous in the callee (explicit interface  as in the same module)  it then made the compiler create a temp on passing the slice which created the stack overflow at that point instead.  Anyway I had already slightly refactored the code to include a loop and the problem no longer exists now so I will add this to things learned and move on.

0 Kudos
Steve_Lionel
Honored Contributor III
1,241 Views

If you passed a contiguous slice, the compiler is supposed to detect that and not make a copy.  Because the dummy argument is assumed-shape, no copy is normally needed. I'm wondering if your slice really was contiguous.

andrew_4619
Honored Contributor II
1,232 Views

"I'm wondering if your slice really was contiguous."  I seems that I went down a Rabbit hole whilst suffering from code blindness. One of my usage cases was indeed not a contiguous slice having looked harder at it. D'oh! 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,271 Views

Steve, I am surprised that the WRITE doesn't have an overload that permits passing a strided array descriptor as opposed to a contiguous block of data.

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,257 Views

Got me. The VAX FORTRAN I/O library, while it didn't know from assumed-shape, did have an API for implied DO loops that could deal with strides. I never worked on the DEC Fortran 90 (and successor) I/O libraries so I don't know what they might be capable of, though looking at assembly code shows some vague similarities. If I were in charge of that library, I'd add such a thing.

0 Kudos
Steve_Lionel
Honored Contributor III
1,191 Views

Good to hear. This is another example of why minimal reproducible examples, rather than code fragments or pseudocode, are important when asking for help with problems.

0 Kudos
Reply