How can I check if a subroutine has been run before? - memory-leaks

I've currently got a Fortran program using the 2008 standard that has a subroutine that loads data from a file if it's the first run of the subroutine. On all runs, the subroutine interpolates over the data and returns two values, but the goal is to avoid reloading the same data from the file.
Initially, I had something like this:
module myModel_mod
use myModelLoader_mod
use linear_interpolation_module
implicit none
contains
subroutine myModel(A, B, C, modelFile, D, E)
real :: A, B, C, D, E
character(len=*) :: modelFile
type(linear_interp_3d), save :: F, G
real, dimension(:), allocatable, save :: As, Bs, Cs
if (.not. allocated(As)) then
call loadModel(modelFile, As, Bs, Cs)
.
. (processing of loaded data and creation of F and G occurs here)
.
end if
call F%evaluate(A, B, C, D)
call G%evaluate(A, B, C, E)
end subroutine
end module
My module makes use of the finterp library. It interpolates a 3D gridded data set for two values, D and E. I'm having to rewrite this part of the code to fix a memory leak, and I'd like to fix where As, Bs, and Cs are left allocated. They don't need the SAVE attribute; it's left over from an older implementation of gridded interpolation I was using. However, if I remove it, then by my understanding, I can't check if As is allocated to see if the subroutine has been run before.
I've considered creating a logical flag variable with the SAVE attribute that gets set when the subroutine runs for the first time, but I believe that would still result in a small memory leak, albeit much smaller than what I currently have.
Is there a way to check for the "first run" condition in a way that doesn't result in a memory leak?

Memory leaks are impossible with allocatable arrays in Fortran. Unsaved allocatable local variables are deallocated on exit from the procedure. The saved ones are retained but cannot grow without limits. You have only a limited number of local allocatable variables that you can allocate and that then take some memory, but they will not grow without control.
To answer your title question, I use the approach with a saved logical variable and if it is about allocating local or module arrays I just use if (allocated()).

Related

How to input a string value of unknown length from console in Fortran? [duplicate]

I would like to use deferred-length character strings in a "simple" manner to read user input. The reason that I want to do this is that I do not want to have to declare the size of a character string before knowing how large the user input will be. I know that there are "complicated" ways to do this. For example, the iso_varying_string module can be used: https://www.fortran.com/iso_varying_string.f95. Also, there is a solution here: Fortran Character Input at Undefined Length. However, I was hoping for something as simple, or almost as simple, as the following:
program main
character(len = :), allocatable :: my_string
read(*, '(a)') my_string
write(*,'(a)') my_string
print *, allocated(my_string), len(my_string)
end program
When I run this program, the output is:
./a.out
here is the user input
F 32765
Notice that there is no output from write(*,'(a)') my_string. Why?
Also, my_string has not been allocated. Why?
Why isn't this a simple feature of Fortran? Do other languages have this simple feature? Am I lacking some basic understanding about this issue in general?
vincentjs's answer isn't quite right.
Modern (2003+) Fortran does allow automatic allocation and re-allocation of strings on assignment, so a sequence of statements such as this
character(len=:), allocatable :: string
...
string = 'Hello'
write(*,*)
string = 'my friend'
write(*,*)
string = 'Hello '//string
write(*,*)
is correct and will work as expected and write out 3 strings of different lengths. At least one compiler in widespread use, the Intel Fortran compiler, does not engage 2003 semantics by default so may raise an error on trying to compile this. Refer to the documentation for the setting to use Fortran 2003.
However, this feature is not available when reading a string so you have to resort to the tried and tested (aka old-fashioned if you prefer) approach of declaring a buffer of sufficient size for any input and of then assigning the allocatable variable. Like this:
character(len=long) :: buffer
character(len=:), allocatable :: string
...
read(*,*) buffer
string = trim(buffer)
No, I don't know why the language standard forbids automatic allocation on read, just that it does.
Deferred length character is a Fortran 2003 feature. Note that many of the complicated methods linked to are written against earlier language versions.
With Fortran 2003 support, reading a complete record into a character variable is relatively straight forward. A simple example with very minimal error handling below. Such a procedure only needs to be written once, and can be customized to suit a user's particular requirements.
PROGRAM main
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: INPUT_UNIT
IMPLICIT NONE
CHARACTER(:), ALLOCATABLE :: my_string
CALL read_line(input_unit, my_string)
WRITE (*, "(A)") my_string
PRINT *, ALLOCATED(my_string), LEN(my_string)
CONTAINS
SUBROUTINE read_line(unit, line)
! The unit, connected for formatted input, to read the record from.
INTEGER, INTENT(IN) :: unit
! The contents of the record.
CHARACTER(:), INTENT(OUT), ALLOCATABLE :: line
INTEGER :: stat ! IO statement IOSTAT result.
CHARACTER(256) :: buffer ! Buffer to read a piece of the record.
INTEGER :: size ! Number of characters read from the file.
!***
line = ''
DO
READ (unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=size) buffer
IF (stat > 0) STOP 'Error reading file.'
line = line // buffer(:size)
! An end of record condition or end of file condition stops the loop.
IF (stat < 0) RETURN
END DO
END SUBROUTINE read_line
END PROGRAM main
Deferred length arrays are just that: deferred length. You still need to allocate the size of the array using the allocate statement before you can assign values to it. Once you allocate it, you can't change the size of the array unless you deallocate and then reallocate with a new size. That's why you're getting a debug error.
Fortran does not provide a way to dynamically resize character arrays like the std::string class does in C++, for example. In C++, you could initialize std::string var = "temp", then redefine it to var = "temporary" without any extra work, and this would be valid. This is only possible because the resizing is done behind the scenes by the functions in the std::string class (it doubles the size if the buffer limit is exceeded, which is functionally equivalent to reallocateing with a 2x bigger array).
Practically speaking, the easiest way I've found when dealing with strings in Fortran is to allocate a reasonably large character array that will fit most expected inputs. If the size of the input exceeds the buffer, then simply increase the size of your array by reallocateing with a larger size. Removing trailing white space can be done using trim.
You know that there are "complicated" ways of doing what you want. Rather than address those, I'll answer your first two "why?"s.
Unlike intrinsic assignment a read statement does not have the target variable first allocated to the correct size and type parameters for the thing coming in (if it isn't already like that). Indeed, it is a requirement that the items in an input list be allocated. Fortran 2008, 9.6.3, clearly states:
If an input item or an output item is allocatable, it shall be allocated.
This is the case whether the allocatable variable is a character with deferred length, a variable with other deferred length-type parameters, or an array.
There is another way to declare a character with deferred length: giving it the pointer attribute. This doesn't help you, though, as we also see
If an input item is a pointer, it shall be associated with a definable target ...
Why you have no output from your write statement is related to why you see that the character variable isn't allocated: you haven't followed the requirements of Fortran and so you can't expect the behaviour that isn't specified.
I'll speculate as to why this restriction is here. I see two obvious ways to relax the restriction
allow automatic allocation generally;
allow allocation of a deferred length character.
The second case would be easy:
If an input item or an output item is allocatable, it shall be allocated unless it is a scalar character variable with deferred length.
This, though, is clumsy and such special cases seem against the ethos of the standard as a whole. We'd also need a carefully thought out rule about alloction for this special case.
If we go for the general case for allocation, we'd presumably require that the unallocated effective item is the final effective item in the list:
integer, allocatable :: a(:), b(:)
character(7) :: ifile = '1 2 3 4'
read(ifile,*) a, b
and then we have to worry about
type aaargh(len)
integer, len :: len
integer, dimension(len) :: a, b
end type
type(aaargh), allocatable :: a(:)
character(9) :: ifile = '1 2 3 4 5'
read(ifile,*) a
It gets quite messy very quickly. Which seems like a lot of problems to resolve where there are ways, of varying difficulty, of solving the read problem.
Finally, I'll also note that allocation is possible during a data transfer statement. Although a variable must be allocated (as the rules are now) when appearing in input list components of an allocated variable of derived type needn't be if that effective item is processed by defined input.

Heap profiling in Haskell. Am I having space leaks?

I am writing a small snake game in Haskell as sort of a guided tutorial for beginners. The "rendering" just takes a Board and produces a Data.ByteString.Builder which is printed in the terminal. (the html profiles are pushed to the repo, you can inspect them without compiling the programm)
The problem
The problem I have is that the heap profiling looks weird: There are many spikes, and suddenly Builder, PAP and BuildStep take as same memory as the rest of the program. Considering that rendering is happenning 10 times in a second (i.e. every second we produce 10 builders), it seems inconsistent that every once in a while the builder just takes that much memory. I don't know if this is considered an space leak, since there is no thunks in the profile, but the PAP doesn't look right (I don't know...)
Implementation
The board is represented as an inmutable array of builders indexed by coordinaates (tuples) type Board = Array (Int, Int) Builder (essentialy, what should be printed in each coordinate). The function which converts the board into a builder is the expected strict fold which handle new lines using height and width of the board.
toBuilder :: RenderState -> Builder
-- |- The Array (Int, Int) Builder
toBuilder (RenderState b binf#(BoardInfo h w) gOver s) =
-- ^^^ height and width
if gOver
then ppScore s <> fst (boardToString $ emptyGrid binf) -- Not interesting. Case of game over print build an empty grid
else ppScore s <> fst (boardToString b) -- print the current board
where
boardToString = foldl' fprint (mempty, 0) -- concatenate builders and count the number, such that when #width builders have been concatenated, add a new line.
fprint (!s, !i) cell =
if ((i + 1) `mod` w) == 0
then (s <> cell <> B.charUtf8 '\n', i + 1 )
else (s <> cell , i + 1)
Up to the .prof file this function take most of the time and space (92%, which is expected). Moreover, this is the only part of the code that produces a big builder, so the problem should be here.
The buffering mode
The above profile happens when BufferMode is set to LineBuffering (default), but interestingly if I change it to NoBuffering then the profile looks the same but a thunk appears and the builder disappear...
The questions
I have reached a point which I don't know whats going on, hence my questions are a little bit vague:
Is my code with line buffering (first profile) actually leaking? No thunk appears but the PAP eating so much memory looks like a warning
The second profile clearly(?) leaks, is there an standard way to inspect which part of the code is producing the thunk?
Am I completely missing something, and actually the profile looks fine?
In case anyone is interested, I think I've found the problem. It is the terminal speed... If I run an smaller board size or a slower rendering time (the picture is for a 50x70 board with 10 renders a second), then the memory usage is completely normal.
What I think is happening, is that the board is printed into the console using B.hPutBuilder stdout, this action takes shorter than the console to actually print it, so the haskell thread continues and creates another board which should wait to be printed because the console is busy. I guess this leads to some how, two boards living in memory for a short time.
Other guesses are welcome!

Is Static Dynamic Array not allowed in RPGLE sub-procedure

SEQ is throwing a RNF3772 error if I try to declare a Static Dynamic array in a RPGLE sub-procedure. Is static dynamic array not allowed in sub-procedure?
Below is an example of what I entered in SEQ. The error that I got is "The keyword is not allowed following keyword STATIC; keyword is ignored."
P proc1 B
D pi
D myArray s 10 dim(1000) static based(myArray_p)
P E
static means the memory is kept (allocated) locally between calls
based means that no memory is allocated locally
So yeah, the two are mutually exclusive...
Unless you're %alloc() memory yourself, there's no dynamic arrays in RPG...I think even the new "dynamic arrays" in 7.4 actually just allocate the max memory. What's nice is they keep track of how many elements are used automatically.
edit2 As Barbara called out, if you are doing %Alloc()/%Realloc() yourself, then all you need is the basing pointer declared static I'd include a parm to indicate the memory should be cleaned up.
P proc1 B
D pi
d cleanUp n value
D myArray s 10 dim(1000) based(myArray_p)
d myArray_p s * static
if cleanUp;
dealloc(myArray_p);
return;
endif;
P E
Just use static. Same memory requirements as if you'd used a global variable, but hidden inside the procedure.
If you really want dynamic arrays, you could build your own routines in a *SRVPGM to use. Or you could make use of some open source.
RPG Next Gen - Vector
RPG Array List/Linked List
RPGMap
Dynamic Array using a user space
With an actual dynamic array, you'd likely end up with a pointer (or maybe an integer) variable in your procedure that you'd want defined as STATIC so that it remains between calls.
You'll also need to consider how to clean up the memory when you are done.
To define your array as based, but have it retain its values between calls, you have to define the basing pointer as static. It will probably be impossible to free the allocated storage except by reclaiming the activation group, unless your procedure has a way of knowing the array is no longer needed for future calls.

Using aligned memory for Fortran FFTs (FFTW) without memory leaks

I want to use the modern Fortran interface of FFTW, but in a way that allows simple function calls like ifftshift(fft_c2c(vec)*exp(vec)) et cetera. This is my understanding of how to do this (I also understand that doing a new plan every call is not the most efficient thing). Currently this code is functional (returns correct results); however, there is a memory leak so that repeated calls result in losses. I'm not quite sure where though! I had hoped that the association of the return variable `fft' with the only unfreed memory would result in no leaks but this is evidently not true. What am I missing, and how can I better structure what I want to do with proper modern fortran? Thanks!
function fft_c2c(x) result(fft)
integer :: N
type(C_PTR) :: plan
complex(C_DOUBLE_COMPLEX), pointer :: fft(:)
complex(C_DOUBLE_COMPLEX), dimension(:), intent(in) :: x
! Use an auxiliary array that is allocated with fftw_alloc_complex
! to ensure memory alignment for performance, see FFTW docs
complex(C_DOUBLE_COMPLEX), pointer :: x_align(:)
type(C_PTR) :: p
N = size(x)
p = fftw_alloc_complex(int(N, C_SIZE_T))
call c_f_pointer(p, fft, [N]);
p = fftw_alloc_complex(int(N, C_SIZE_T))
call c_f_pointer(p, x_align, [N]);
plan = fftw_plan_dft_1d(N, x_align, fft, FFTW_FORWARD, FFTW_MEASURE);
! FFTW overwrites x_align and fft during planning process, so assign
! data here
x_align = x
call fftw_execute_dft(plan, x_align, fft);
call fftw_free(p);
end function fft_c2c
You can't do that easily. You are forcing your notin of "modern"="everything is a function" on Fortran, here it does not fit that well (or not at all).
For the meory leaks the rule is simple - deallocate all the pointers. Using them for the result variable is a guarantee of a memory leak. If you need local allocted aligned memory, you need to locally allocate it, copy the data there, copy the data out and deallocate it.
Every pointer in Fortran need explicit deallocation, there is no reference counting or garbage collection to deallocate them for you.
You think about just using the nonaligned memory with the appropriate flags and measure the difference, you seem not to care about the top performance anyway.
Finally, doingFFTW_MEASURE before every transform is not just "not the most efficient thing", it is an absolute performance disaster. You should, at the very least, use FFTW_ESTIMATE to mitigate it.

No error message in Haskell

Just out of curiosity, I made a simple script to check speed and memory efficiency of constructing a list in Haskell:
wasteMem :: Int -> [Int]
wasteMem 0 = [199]
wasteMem x = (12432483483467856487256348746328761:wasteMem (x-1))
main = do
putStrLn("hello")
putStrLn(show (wasteMem 10000000000000000000000000000000000))
The strange thing is, when I tried this, it didn't run out of memory or stack space, it only prints [199], the same as running wasteMem 0. It doesn't even print an error message... why? Entering this large number in ghci just prints the number, so I don't think it's a rounding or reading error.
Your program is using a number greater than maxBound :: Int32. This means it will behave differently on different platforms. For GHC x86_64 Int is 64 bits (32 bits otherwise, but the Haskell report only promises 29 bits). This means your absurdly large value (1x10^34) is represented as 4003012203950112768 for me and zero for you 32-bit folks:
GHCI> 10000000000000000000000000000000000 :: Int
4003012203950112768
GHCI> 10000000000000000000000000000000000 :: Data.Int.Int32
0
This could be made platform independent by either using a fixed-size type (ex: from Data.Word or Data.Int) or using Integer.
All that said, this is a poorly conceived test to begin with. Haskell is lazy, so the amount of memory consumed by wastedMem n for any value n is minimal - it's just a thunk. Once you try to show this result it will grab elements off the list one at a time - first generating "[12432483483467856487256348746328761, and leaving the rest of the list as a thunk. The first value can be garbage collected before the second value is even considered (a constant-space program).
Adding to Thomas' answer, if you really want to waste space, you have to perform an operation on the list, which needs the whole list in memory at once. One such operation is sorting:
print . sort . wasteMem $ (2^16)
Also note that it's almost impossible to estimate the run-time memory usage of your list. If you want a more predictable memory benchmark, create an unboxed array instead of a list. This also doesn't require any complicated operation to ensure that everything stays in memory. Indexing a single element in an array already makes sure that the array is in memory at least once.

Resources