FV3 Bundle
mpp_memutils.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
20 
21  use mpp_mod, only: mpp_min, mpp_max, mpp_sum, mpp_pe, mpp_root_pe
22  use mpp_mod, only: mpp_error, fatal, stderr, mpp_npes, get_unit
23 
24  implicit none
25  private
26 
29 
30  real :: begin_memuse
31  logical :: memuse_started = .false.
32 
33 contains
34 
35  !#######################################################################
36  subroutine mpp_memuse_begin
37 #if defined(__sgi) || defined(__aix) || defined(__SX)
38  integer :: memuse
39 #endif
40 
41  if(memuse_started) then
42  call mpp_error(fatal, "mpp_memutils_mod: mpp_memuse_begin was already called")
43  endif
44  memuse_started = .true.
45 
46 #if defined(__sgi) || defined(__aix) || defined(__SX)
47  begin_memuse = memuse()*1e-3
48 #else
50 #endif
51 
52  end subroutine mpp_memuse_begin
53 
54  !#######################################################################
55  subroutine mpp_memuse_end( text, unit )
56 
57  character(len=*), intent(in) :: text
58  integer, intent(in), optional :: unit
59  real :: m, mmin, mmax, mavg, mstd, end_memuse
60  integer :: mu
61 #if defined(__sgi) || defined(__aix) || defined(__SX)
62  integer :: memuse
63 #endif
64 
65  if(.NOT.memuse_started) then
66  call mpp_error(fatal, "mpp_memutils_mod: mpp_memuse_begin must be called before calling mpp_memuse_being")
67  endif
68  memuse_started = .false.
69 
70 #if defined(__sgi) || defined(__aix) || defined(__SX)
71  end_memuse = memuse()*1e-3
72 #else
73  call mpp_mem_dump(end_memuse)
74 #endif
75 
76  mu = stderr(); if( PRESENT(unit) )mu = unit
77  m = end_memuse - begin_memuse
78  mmin = m; call mpp_min(mmin)
79  mmax = m; call mpp_max(mmax)
80  mavg = m; call mpp_sum(mavg); mavg = mavg/mpp_npes()
81  mstd = (m-mavg)**2; call mpp_sum(mstd); mstd = sqrt( mstd/mpp_npes() )
82  if( mpp_pe().EQ.mpp_root_pe() )write( mu,'(a64,4es11.3)' ) &
83  'Memory(MB) used in '//trim(text)//'=', mmin, mmax, mstd, mavg
84 
85  return
86 
87  end subroutine mpp_memuse_end
88 
89  !#######################################################################
90 
91  subroutine mpp_print_memuse_stats( text, unit )
92 
93  character(len=*), intent(in) :: text
94  integer, intent(in), optional :: unit
95  real :: m, mmin, mmax, mavg, mstd
96  integer :: mu
97 !memuse is an external function: works on SGI
98 !use #ifdef to generate equivalent on other platforms.
99 #if defined(__sgi) || defined(__aix) || defined(__SX)
100  integer :: memuse !default integer OK?
101 #endif
102 
103  mu = stderr(); if( PRESENT(unit) )mu = unit
104 #if defined(__sgi) || defined(__aix) || defined(__SX)
105  m = memuse()*1e-3
106 #else
107  call mpp_mem_dump(m)
108 #endif
109  mmin = m; call mpp_min(mmin)
110  mmax = m; call mpp_max(mmax)
111  mavg = m; call mpp_sum(mavg); mavg = mavg/mpp_npes()
112  mstd = (m-mavg)**2; call mpp_sum(mstd); mstd = sqrt( mstd/mpp_npes() )
113  if( mpp_pe().EQ.mpp_root_pe() )write( mu,'(a64,4es11.3)' ) &
114  'Memuse(MB) at '//trim(text)//'=', mmin, mmax, mstd, mavg
115 
116  return
117  end subroutine mpp_print_memuse_stats
118 
119 !#######################################################################
120 
121 subroutine mpp_mem_dump ( memuse )
123 real, intent(out) :: memuse
124 
125 ! This routine returns the memory usage on Linux systems.
126 ! It does this by querying a system file (file_name below).
127 ! It is intended for use by print_memuse_stats above.
128 
129 character(len=32) :: file_name = '/proc/self/status'
130 character(len=32) :: string
131 integer :: mem_unit
132 real :: multiplier
133 
134  memuse = 0.0
135  multiplier = 1.0
136 
137  mem_unit = get_unit()
138  open(mem_unit, file=file_name, form='FORMATTED', action='READ', access='SEQUENTIAL')
139 
140  do; read (mem_unit,'(a)', end=10) string
141  if ( index( string, 'VmHWM:' ) == 1 ) then
142  read (string(7:len_trim(string)-2),*) memuse
143  exit
144  endif
145  enddo
146 
147  if (trim(string(len_trim(string)-1:)) == "kB" ) &
148  multiplier = 1.0/1024. ! Convert from kB to MB
149 
150 10 close (mem_unit)
151  memuse = memuse * multiplier
152 
153  return
154 end subroutine mpp_mem_dump
155 
156 
157 end module mpp_memutils_mod
subroutine, public mpp_memuse_begin
subroutine, public mpp_mem_dump(memuse)
Definition: mpp.F90:39
subroutine, public mpp_print_memuse_stats(text, unit)
subroutine, public mpp_memuse_end(text, unit)
logical memuse_started