← back to index

src/framework/MOM_write_cputime.F90

portedportable, not yet portedexecuted, not portableexecutable, not hit by this run

1! This file is part of MOM6, the Modular Ocean Model version 6.
2! See the LICENSE file for licensing information.
3! SPDX-License-Identifier: Apache-2.0
4
5!> A module to monitor the overall CPU time used by MOM6 and project when to stop the model
6module MOM_write_cputime
7
8use MOM_coms, only : sum_across_PEs, num_pes
9use MOM_error_handler, only : MOM_error, MOM_mesg, FATAL, is_root_pe
10use MOM_io, only : open_ASCII_file, close_file, APPEND_FILE, WRITEONLY_FILE
11use MOM_file_parser, only : get_param, log_param, log_version, param_file_type
12use MOM_time_manager, only : time_type, get_time, operator(>)
13
14implicit none ; private
15
16public write_cputime, MOM_write_cputime_init, MOM_write_cputime_end, write_cputime_start_clock
17
18!-----------------------------------------------------------------------
19
20integer :: CLOCKS_PER_SEC = 1000 !< The number of clock cycles per second, used by the system clock
21integer :: MAX_TICKS = 1000 !< The number of ticks per second, used by the system clock
22
23!> A control structure that regulates the writing of CPU time
24type, public :: write_cputime_CS ; private
25 logical :: initialized = .false. !< True if this control structure has been initialized.
26 real :: maxcpu !< The maximum amount of CPU time per processor
27 !! for which MOM should run before saving a restart
28 !! file and quitting with a return value that
29 !! indicates that further execution is required to
30 !! complete the simulation [wall-clock seconds].
31 type(time_type) :: Start_time !< The start time of the simulation.
32 !! Start_time is set in MOM_initialization.F90
33 real :: startup_cputime !< The CPU time used in the startup phase of the model [clock_cycles].
34 real :: prev_cputime = 0.0 !< The last measured CPU time [clock_cycles].
35 real :: dn_dcpu_min = -1.0 !< The minimum derivative of timestep with CPU time [steps clock_cycles-1].
36 real :: cputime2 = 0.0 !< The accumulated CPU time [clock_cycles].
37 integer :: previous_calls = 0 !< The number of times write_CPUtime has been called.
38 integer :: prev_n = 0 !< The value of n from the last call.
39 integer :: fileCPU_ascii= -1 !< The unit number of the CPU time file.
40 character(len=200) :: CPUfile !< The name of the CPU time file.
41end type write_cputime_CS
42
43contains
44
45!> Evaluate the CPU time returned by SYSTEM_CLOCK at the start of a run
461subroutine write_cputime_start_clock(CS)
47 type(write_cputime_CS), pointer :: CS !< The control structure set up by a previous
48 !! call to MOM_write_cputime_init.
49 integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
501 if (.not.associated(CS)) allocate(CS)
51
521 call SYSTEM_CLOCK(new_cputime, CLOCKS_PER_SEC, MAX_TICKS)
531 CS%prev_cputime = new_cputime
541end subroutine write_cputime_start_clock
55
56!> Initialize the MOM_write_cputime module.
571subroutine MOM_write_cputime_init(param_file, directory, Input_start_time, CS)
58 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
59 character(len=*), intent(in) :: directory !< The directory where the CPU time file goes.
60 type(time_type), intent(in) :: Input_start_time !< The start model time of the simulation.
61 type(write_cputime_CS), pointer :: CS !< A pointer that may be set to point to the
62 !! control structure for this module.
63
64 ! Local variables
65 integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK
66 ! This include declares and sets the variable "version".
67# include "version_variable.h"
68 character(len=40) :: mdl = 'MOM_write_cputime' ! This module's name.
69 logical :: all_default ! If true, all parameters are using their default values.
70
711 if (.not.associated(CS)) then
720 allocate(CS)
730 call SYSTEM_CLOCK(new_cputime, CLOCKS_PER_SEC, MAX_TICKS)
740 CS%prev_cputime = new_cputime
75 endif
76
771 CS%initialized = .true.
78
79 ! Read all relevant parameters and write them to the model log.
80
81 ! Determine whether all parameters are set to their default values.
821 call get_param(param_file, mdl, "MAXCPU", CS%maxcpu, units="wall-clock seconds", default=-1.0, do_not_log=.true.)
831 call get_param(param_file, mdl, "CPU_TIME_FILE", CS%CPUfile, default="CPU_stats", do_not_log=.true.)
841 all_default = (CS%maxcpu == -1.0) .and. (trim(CS%CPUfile) == trim("CPU_stats"))
85
861 call log_version(param_file, mdl, version, "", all_default=all_default)
87 call get_param(param_file, mdl, "MAXCPU", CS%maxcpu, &
88 "The maximum amount of cpu time per processor for which "//&
89 "MOM should run before saving a restart file and "//&
90 "quitting with a return value that indicates that a "//&
91 "further run is required to complete the simulation. "//&
92 "If automatic restarts are not desired, use a negative "//&
93 "value for MAXCPU. MAXCPU has units of wall-clock "//&
94 "seconds, so the actual CPU time used is larger by a "//&
95 "factor of the number of processors used.", &
961 units="wall-clock seconds", default=-1.0)
97 call get_param(param_file, mdl, "CPU_TIME_FILE", CS%CPUfile, &
981 "The file into which CPU time is written.",default="CPU_stats")
991 CS%CPUfile = trim(directory)//trim(CS%CPUfile)
1001 call log_param(param_file, mdl, "directory/CPU_TIME_FILE", CS%CPUfile)
101#ifdef STATSLABEL
102 CS%CPUfile = trim(CS%CPUfile)//"."//trim(adjustl(STATSLABEL))
103#endif
104
1051 CS%Start_time = Input_start_time
106
1071end subroutine MOM_write_cputime_init
108
109!> Close the MOM_write_cputime module.
1101subroutine MOM_write_cputime_end(CS)
111 type(write_cputime_CS), pointer :: CS !< The control structure set up by a previous
112 !! call to MOM_write_cputime_init.
113
1141 if (.not.associated(CS)) return
115
116 ! Flush and close the output files.
1171 if (is_root_pe() .and. CS%fileCPU_ascii > 0) then
1180 flush(CS%fileCPU_ascii)
1190 call close_file(CS%fileCPU_ascii)
120 endif
121
1221 deallocate(CS)
123
124end subroutine MOM_write_cputime_end
125
126!> This subroutine assesses how much CPU time the model has taken and determines how long the model
127!! should be run before it saves a restart file and stops itself. Optionally this may also be used
128!! to trigger this module's end routine.
1292subroutine write_cputime(day, n, CS, nmax, call_end)
130 type(time_type), intent(inout) :: day !< The current model time.
131 integer, intent(in) :: n !< The time step number of the current execution.
132 type(write_cputime_CS), pointer :: CS !< The control structure set up by a previous
133 !! call to MOM_write_cputime_init.
134 integer, optional, intent(inout) :: nmax !< The number of iterations after which to stop so
135 !! that the simulation will not run out of CPU time.
136 logical, optional, intent(in) :: call_end !< If true, also call MOM_write_cputime_end.
137
138 ! Local variables
139 real :: d_cputime ! The change in CPU time since the last call
140 ! this subroutine [clock_cycles]
141 integer :: new_cputime ! The CPU time returned by SYSTEM_CLOCK [clock_cycles]
142 real :: reday ! The time in days, including fractional days [days]
143 integer :: start_of_day ! The number of seconds since the start of the day
144 integer :: num_days ! The number of days in the time
145
1462 if (.not.associated(CS)) call MOM_error(FATAL, &
1470 "write_energy: Module must be initialized before it is used.")
148
1492 if (.not.CS%initialized) call MOM_error(FATAL, &
1500 "write_cputime: Module must be initialized before it is used.")
151
1522 call SYSTEM_CLOCK(new_cputime, CLOCKS_PER_SEC, MAX_TICKS)
153! The following lines extract useful information even if the clock has rolled
154! over, assuming a 32-bit SYSTEM_CLOCK. With more bits, rollover is essentially
155! impossible. Negative fluctuations of less than 10 seconds are not interpreted
156! as the clock rolling over. This should be unnecessary but is sometimes needed
157! on the GFDL SGI/O3k.
1582 if (new_cputime < CS%prev_cputime-(10.0*CLOCKS_PER_SEC)) then
1590 d_cputime = new_cputime - CS%prev_cputime + MAX_TICKS
160 else
1612 d_cputime = new_cputime - CS%prev_cputime
162 endif
163
1642 call sum_across_PEs(d_cputime)
1652 if (CS%previous_calls == 0) CS%startup_cputime = d_cputime
166
1672 CS%cputime2 = CS%cputime2 + d_cputime
168
1692 if ((CS%previous_calls >= 1) .and. (CS%maxcpu > 0.0)) then
170 ! Determine the slowest rate at which time steps are executed.
1710 if ((n > CS%prev_n) .and. (d_cputime > 0.0) .and. &
172 ((CS%dn_dcpu_min*d_cputime < (n - CS%prev_n)) .or. &
173 (CS%dn_dcpu_min < 0.0))) &
1740 CS%dn_dcpu_min = (n - CS%prev_n) / d_cputime
1750 if (present(nmax) .and. (CS%dn_dcpu_min >= 0.0)) then
176 ! Have the model stop itself after 95% of the CPU time has been used.
177 nmax = n + INT( CS%dn_dcpu_min * &
178 (0.95*CS%maxcpu * REAL(num_pes())*CLOCKS_PER_SEC - &
1790 (CS%startup_cputime + CS%cputime2)) )
180! write(mesg,*) "Resetting nmax to ",nmax," at day",reday
181! call MOM_mesg(mesg)
182 endif
183 endif
1842 CS%prev_cputime = new_cputime ; CS%prev_n = n
185
1862 call get_time(day, start_of_day, num_days)
1872 reday = REAL(num_days)+ (REAL(start_of_day)/86400.0)
188
189 ! Reopen or create a text output file.
1902 if ((CS%previous_calls == 0) .and. (is_root_pe())) then
1911 if (day > CS%Start_time) then
1920 call open_ASCII_file(CS%fileCPU_ascii, trim(CS%CPUfile), action=APPEND_FILE)
193 else
1941 call open_ASCII_file(CS%fileCPU_ascii, trim(CS%CPUfile), action=WRITEONLY_FILE)
195 endif
196 endif
197
1982 if (is_root_pe()) then
1992 if (CS%previous_calls == 0) then
200 write(CS%fileCPU_ascii, &
201 '("Startup CPU time: ", F12.3, " sec summed across", I5, " PEs.")') &
2021 (CS%startup_cputime / CLOCKS_PER_SEC), num_pes()
2031 write(CS%fileCPU_ascii,*)" Day, Step number, CPU time, CPU time change"
204 endif
205 write(CS%fileCPU_ascii,'(F12.3,", ",I11,", ",F12.3,", ",F12.3)') &
2062 reday, n, (CS%cputime2 / real(CLOCKS_PER_SEC)), &
2074 d_cputime / real(CLOCKS_PER_SEC)
208
2092 flush(CS%fileCPU_ascii)
210 endif
2112 CS%previous_calls = CS%previous_calls + 1
212
2132 if (present(call_end)) then
2141 if (call_end) call MOM_write_cputime_end(CS)
215 endif
216
2172end subroutine write_cputime
218
219!> \namespace mom_write_cputime
220!!
221!! By Robert Hallberg, May 2006.
222!!
223!! This file contains the subroutine (write_cputime) that writes
224!! the summed CPU time across all processors to an output file. In
225!! addition, write_cputime estimates how many more time steps can be
226!! taken before 95% of the available CPU time is used, so that the
227!! model can be checkpointed at that time.
228
2290end module MOM_write_cputime