In addition to several excellent suggestions on how to track down a possible memory leak listed above, perhaps you are worried about the amount of memory used as you need a value to give a job scheduler or are hitting a limit on how many program instances you can run on a particular node. In that case you might want the program to always generate a usage report. There are several possible ways to do that internally or externally ( e.g. the time(1) command, an accounting command often available via a job scheduler ( such as LSF, OpenPBS, Torque, Slurm, …).
It is much easier now to call C routines such as getrusage but an often overlooked
option on Linux is to open and print data from the /proc/self directory, where you can usually (varies a bit by platform) get memory high-water marks, system and user CPU time and all kinds of info for making a nice resource report without doing
anything other than OPEN and READ/WRITE calls. For example
program main
implicit none
real :: r(1000000000/4), rnd
write(*,*)'just the array should take=',nint(real(storage_size(r))/8.0*size(r)/1024),'KB'
write(*,*)'but resident size likely smaller'
call pstatus()
write(*,*)'until used or intialized'
r=0
call pstatus()
call random_number(rnd)
write(*,*)'so compiler does not optimize away',r(size(r)*rnd)
contains
subroutine pstatus()
!@(#) print Linux status for current PID
character(len=256) :: iomsg, line
integer :: iostat, lun
open(newunit=lun,file='/proc/self/status',iostat=iostat,iomsg=iomsg)
if(iostat.eq.0)then
do
read(lun,'(a)',iostat=iostat)line
if(iostat.ne.0)exit
if(index(line,'Vm').eq.1)then
if(index(line,'RSS').ne.0)then
write(*,'(*(a))')trim(line),' <==='
else
write(*,'(a)')trim(line)
endif
endif
enddo
endif
close(unit=lun,iostat=iostat)
end subroutine pstatus
end program main
Shows that just declaring an array usually does not cause it to be allocated on the spot, but initializing it usually does (which can be a good or bad thing depending on
where in the scope you initialize it, how often, …). So you might initialize the arrays in a debug version to eliminate a lot of small allocations if looking for the leak, for example.
just the array should take= 976563 KB
but resident size likely smaller
VmSize: 983936 kB
VmLck: 0 kB
VmRSS: 5440 kB <===
VmData: 1088 kB
VmStk: 0 kB
VmExe: 64 kB
VmLib: 2816 kB`
until used or intialized
VmSize: 986048 kB
VmLck: 0 kB
VmRSS: 984128 kB <===
VmData: 979712 kB
VmStk: 0 kB
VmExe: 64 kB
VmLib: 2880 kB
although particularly when using high optimizations you may see a surprising variation in the numbers reported.
If the coding style is to allocate everything with declarations or in a common or global area in global scope (basically you had little choice but to do that without using custom loader commands with most f77 compilers) you could simple use
$ size build/*/app/mem|column -t
text data bss dec hex filename
5581 1436 1000000448 1000007465 3b9ae729 build/gfortran_688A5DB7BAD2F9DA/app/mem
5989 1484 1000000448 1000007921 3b9ae8f1 build/gfortran_E167FD2A985B468F/app/mem
(The number of interest is usually under “dec” and in bytes.)
and see the size the program is declaring at startup what it is going to use, but that often just gives you a
minimum now (which can still be useful).