- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page