Skip to content

Commit a388e58

Browse files
committed
Add WallTimeReport callback
Add CLI arg for walltime logging Make suggested changtes; move cb into src; add tests
1 parent 98eaaef commit a388e58

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

experiments/ClimaEarth/cli_options.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ function argparse_settings()
145145
help = "An optional YAML file used to overwrite the default model parameters."
146146
arg_type = String
147147
default = nothing
148+
"--atmos_log_progress"
149+
help = "Use the ClimaAtmos walltime logging callback instead of the default ClimaCoupler one [`false` (default), `true`]"
150+
arg_type = Bool
151+
default = false
148152
"--albedo_model"
149153
help = "Type of albedo model. [`ConstantAlbedo`, `RegressionFunctionAlbedo`, `CouplerAlbedo` (default)]"
150154
arg_type = String

experiments/ClimaEarth/components/atmosphere/climaatmos.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ function get_atmos_config_dict(
626626
# can pick up from where we have left. NOTE: This should not be needed, but
627627
# there is no easy way to initialize ClimaAtmos with a different t_start
628628
atmos_config["dt_save_state_to_disk"] = coupler_config["checkpoint_dt"]
629+
atmos_config["log_progress"] = coupler_config["atmos_log_progress"]
629630

630631
# The Atmos `get_simulation` function expects the atmos config to contains its timestep size
631632
# in the `dt` field. If there is a `dt_atmos` field in coupler_config, we add it to the atmos config as `dt`

experiments/ClimaEarth/setup_run.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,13 @@ function CoupledSimulation(config_dict::AbstractDict)
497497
checkpoint_cb =
498498
TimeManager.Callback(schedule_checkpoint, sim -> Checkpointer.checkpoint_sims(sim))
499499

500-
callbacks = (checkpoint_cb,)
500+
# Don't use coupler walltime logging if atmos is using its own walltime logging is true
501+
if config_dict["atmos_log_progress"]
502+
callbacks = (checkpoint_cb,)
503+
else
504+
walltime_cb = TimeManager.capped_geometric_walltime_cb(t_start, t_end, Δt_cpl)
505+
callbacks = (checkpoint_cb, walltime_cb)
506+
end
501507

502508
#= Set up default AMIP diagnostics
503509
Use ClimaDiagnostics for default AMIP diagnostics, which currently include turbulent energy fluxes.

src/TimeManager.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module TimeManager
99
import Dates
1010
import ..Interfacer
1111
import ..Utilities: time_to_seconds
12+
import ClimaUtilities.OnlineLogging: WallTimeInfo, report_walltime
1213

1314
"""
1415
time_to_period(s::String)
@@ -100,4 +101,28 @@ function (::NeverSchedule)(args...)
100101
return false
101102
end
102103

104+
"""
105+
capped_geometric_walltime_cb(t_start, t_end, Δt_cpl)
106+
107+
Create a callback that reports walltime at when the number of steps taken is a power of 2, or
108+
when the percent of the simulation that is completed is a multiple of 5. This skips the
109+
first two steps to avoid compilation time noise.
110+
"""
111+
function capped_geometric_walltime_cb(t_start, t_end, Δt_cpl)
112+
tot_steps = Int(ceil(float(t_end - t_start) / float(Δt_cpl)))
113+
five_percent_steps = ceil(Int, 0.05 * tot_steps)
114+
steps_taken = (integrator) -> float(integrator.t - t_start) / float(Δt_cpl)
115+
walltime_report_cond =
116+
(integrator) -> begin
117+
nsteps = steps_taken(integrator)
118+
# skip first two steps for compilation
119+
(nsteps <= 2) && return false
120+
return nsteps % five_percent_steps == 0 || ispow2(nsteps)
121+
end
122+
walltime_affect! = let wt = WallTimeInfo()
123+
(coupled_sim) -> report_walltime(wt, coupled_sim.model_sims.atmos_sim.integrator)
124+
end
125+
return TimeManager.Callback(walltime_report_cond, walltime_affect!)
126+
end
127+
103128
end

test/utilities_tests.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Test: @testset, @test
55
import ClimaComms
66
ClimaComms.@import_required_backends
77
import ClimaCoupler: Utilities
8+
import ClimaCoupler: TimeManager
89
import ClimaCore as CC
910

1011
# Initialize MPI context, in case
@@ -71,4 +72,31 @@ for FT in (Float32, Float64)
7172
)
7273
@test Utilities.integral(ones(space3d)) == sum(ones(space3d))
7374
end
75+
76+
@testset "WallTime Callback" begin
77+
t_start = 0.0
78+
t_end = 10.0
79+
Δt_cpl = 0.1
80+
81+
cb = TimeManager.capped_geometric_walltime_cb(t_start, t_end, Δt_cpl)
82+
83+
# First two steps should not trigger
84+
fake_integrator = (; t = t_start + Δt_cpl)
85+
@test !cb.schedule(fake_integrator)
86+
fake_integrator = (; t = t_start + Δt_cpl * 2)
87+
@test !cb.schedule(fake_integrator)
88+
# step 4, 8, 16 should trigger
89+
fake_integrator = (; t = t_start + Δt_cpl * 4)
90+
@test cb.schedule(fake_integrator)
91+
fake_integrator = (; t = t_start + Δt_cpl * 8)
92+
@test cb.schedule(fake_integrator)
93+
fake_integrator = (; t = t_start + Δt_cpl * 14)
94+
@test !cb.schedule(fake_integrator)
95+
fake_integrator = (; t = t_start + Δt_cpl * 16)
96+
@test cb.schedule(fake_integrator)
97+
98+
# 20% should trigger
99+
fake_integrator = (; t = t_start + Δt_cpl * 20)
100+
@test cb.schedule(fake_integrator)
101+
end
74102
end

0 commit comments

Comments
 (0)