2
2
Our goal here is to output a table displaying some results from benchmark runs
3
3
in the coupler. We want to be able to compare between CPU and GPU runs, as well
4
4
as between coupled and atmos-only runs. The metrics we want to compare are
5
- SYPD, allocations, and the maximum, median, and mean differences between the
6
- CPU and GPU states.
5
+ SYPD, memory usage, allocations, and the maximum, median, and mean differences
6
+ between the CPU and GPU states.
7
7
8
8
The table should look something like this (note that the last 3 columns will be
9
9
added in a future PR):
@@ -12,11 +12,11 @@ added in a future PR):
12
12
------------------------------------------------------------------------------------
13
13
| | $job_id | $job_id | | | |
14
14
| Coupled run | $SYPD | $SYPD | $max_diff | $median_diff | $mean_diff |
15
- | | $cpu_allocs | $cpu_allocs | | | |
15
+ | | $cpu_max_rss | $cpu_max_rss | | | |
16
16
------------------------------------------------------------------------------------
17
17
| | $job_id | $job_id | | | |
18
18
| Atmos-only | $SYPD | $SYPD | $max_diff | $median_diff | $mean_diff |
19
- | | $cpu_allocs | $cpu_allocs | | | |
19
+ | | $cpu_max_rss | $cpu_max_rss | | | |
20
20
------------------------------------------------------------------------------------
21
21
22
22
=#
@@ -37,15 +37,19 @@ function argparse_settings()
37
37
arg_type = String
38
38
default = nothing
39
39
" --cpu_job_id_atmos"
40
- help = " The name of the CPU atmos-only run we want to compare. User must specify CPU and/or GPU atmos-only run name."
40
+ help = " The name of the CPU atmos-only run without diagnostic EDMF we want to compare. User must specify CPU and/or GPU atmos-only non-EDMF run name."
41
41
arg_type = String
42
42
default = nothing
43
43
" --gpu_job_id_atmos"
44
44
help = " The name of the GPU atmos-only run we want to compare."
45
45
arg_type = String
46
46
default = nothing
47
- " --mode_name"
48
- help = " The mode of the simulations being compared (`slabplanet` or `AMIP`)."
47
+ " --cpu_job_id_atmos_diagedmf"
48
+ help = " The name of the CPU atmos-only run with diagnostic EDMF we want to compare. User must specify CPU and/or GPU atmos-only EDMF run name."
49
+ arg_type = String
50
+ default = nothing
51
+ " --gpu_job_id_atmos_diagedmf"
52
+ help = " The name of the GPU atmos-only run we want to compare."
49
53
arg_type = String
50
54
default = nothing
51
55
" --coupler_output_dir"
@@ -60,97 +64,123 @@ function argparse_settings()
60
64
return s
61
65
end
62
66
63
- # Parse command line arguments
64
- parsed_args = ArgParse. parse_args (ARGS , argparse_settings ())
67
+ """
68
+ get_run_info(parsed_args, run_type)
69
+
70
+ Use the input `parsed_args` to get the job ID and artifacts directories for
71
+ both the CPU and GPU runs of the given `run_type`.
72
+
73
+ `run_type` must be one of "coupled", "atmos", or "atmos_diagedmf".
74
+ """
75
+ function get_run_info (parsed_args, run_type)
76
+ # Read in CPU and GPU job ID info from command line
77
+ if run_type == " coupled"
78
+ cpu_job_id = parsed_args[" cpu_job_id_coupled" ]
79
+ gpu_job_id = parsed_args[" gpu_job_id_coupled" ]
80
+ mode_name = " amip"
81
+ elseif run_type == " atmos_diagedmf"
82
+ cpu_job_id = parsed_args[" cpu_job_id_atmos_diagedmf" ]
83
+ gpu_job_id = parsed_args[" gpu_job_id_atmos_diagedmf" ]
84
+ mode_name = " climaatmos"
85
+ elseif run_type == " atmos"
86
+ cpu_job_id = parsed_args[" cpu_job_id_atmos" ]
87
+ gpu_job_id = parsed_args[" gpu_job_id_atmos" ]
88
+ mode_name = " climaatmos"
89
+ else
90
+ error (" Invalid run type: $run_type " )
91
+ end
65
92
66
- # Access buildkite pipeline ID (from `BUILDKITE_GITHUB_DEPLOYMENT_ID` variable)
67
- build_id = parsed_args[" build_id" ]
68
- if ! isnothing (build_id)
69
- build_id_str = " Build ID: $build_id "
70
- else
71
- build_id_str = " Build ID: N/A"
72
- end
93
+ # Verify that the user has provided the necessary job IDs
94
+ # If only one job ID of the CPU/GPU run pair is provided, the other will be inferred
95
+ if isnothing (cpu_job_id) && isnothing (gpu_job_id)
96
+ error (" Must pass CPU and/or GPU coupled run name to compare them." )
97
+ elseif isnothing (gpu_job_id)
98
+ gpu_job_id = " gpu_" * cpu_job_id
99
+ elseif isnothing (cpu_job_id)
100
+ cpu_job_id = gpu_job_id[5 : end ]
101
+ end
73
102
74
- # Construct CPU and GPU artifacts directories
75
- output_dir = parsed_args[" coupler_output_dir" ]
103
+ # Construct CPU and GPU artifacts directories
104
+ cpu_artifacts_dir = joinpath (output_dir, mode_name, cpu_job_id) * " _artifacts"
105
+ gpu_artifacts_dir = joinpath (output_dir, mode_name, gpu_job_id) * " _artifacts"
76
106
77
- # Coupled runs
78
- # Read in CPU and GPU run name info from command line
79
- cpu_job_id_coupled = parsed_args[" cpu_job_id_coupled" ]
80
- gpu_job_id_coupled = parsed_args[" gpu_job_id_coupled" ]
81
- if isnothing (cpu_job_id_coupled) && isnothing (gpu_job_id_coupled)
82
- error (" Must pass CPU and/or GPU coupled run name to compare them." )
83
- elseif isnothing (gpu_job_id_coupled)
84
- gpu_job_id_coupled = " gpu_" * cpu_job_id_coupled
85
- elseif isnothing (cpu_job_id_coupled)
86
- cpu_job_id_coupled = gpu_job_id_coupled[5 : end ]
107
+ return (cpu_job_id, gpu_job_id, cpu_artifacts_dir, gpu_artifacts_dir)
87
108
end
88
109
89
- # Read in mode name from command line (or retrieve from run name).
90
- # Note that we expect this to be the same for all 4 simulations being compared.
91
- mode_name = parsed_args[" mode_name" ]
92
- if isnothing (mode_name)
93
- mode_name =
94
- occursin (" amip" , cpu_job_id_coupled) ? " amip" :
95
- (occursin (" slabplanet" , cpu_job_id_coupled) ? " slabplanet" : error (" Please provide a valid `mode_name`." ))
96
- end
110
+ """
111
+ get_run_data(artifacts_dir)
97
112
98
- gpu_artifacts_dir_coupled = joinpath (output_dir, mode_name, gpu_job_id_coupled) * " _artifacts "
99
- cpu_artifacts_dir_coupled = joinpath (output_dir, mode_name, cpu_job_id_coupled) * " _artifacts "
100
-
101
- # Atmos-only runs
102
- # Read in CPU and GPU run name info from command line
103
- cpu_job_id_atmos = parsed_args[ " cpu_job_id_atmos " ]
104
- gpu_job_id_atmos = parsed_args[ " gpu_job_id_atmos " ]
105
- if isnothing (cpu_job_id_atmos) && isnothing (gpu_job_id_atmos)
106
- error ( " Must pass CPU and/or GPU coupled run name to compare them. " )
107
- elseif isnothing (gpu_job_id_atmos)
108
- gpu_job_id_atmos = " gpu_ " * cpu_job_id_atmos
109
- elseif isnothing (cpu_job_id_atmos)
110
- cpu_job_id_atmos = gpu_job_id_atmos[ 5 : end ]
111
- cpu_artifacts_dir_atmos = joinpath (output_dir, cpu_job_id_atmos )
113
+ Read in run data from artifacts directories, currently SYPD and max RSS on the CPU.
114
+ "" "
115
+ function get_run_data (artifacts_dir)
116
+ # Read in SYPD info
117
+ sypd = open ( joinpath (artifacts_dir, " sypd.txt " ), " r " ) do sypd_file
118
+ round ( parse (Float64, read (sypd_file, String)), digits = 4 )
119
+ end
120
+
121
+ # Read in max RSS info
122
+ cpu_max_rss = open ( joinpath (artifacts_dir, " max_rss_cpu.txt " ), " r " ) do cpu_max_rss_file
123
+ read (cpu_max_rss_file, String)
124
+ end
125
+
126
+ return (sypd, cpu_max_rss )
112
127
end
113
128
114
- mode_name_atmos = " climaatmos"
115
- gpu_artifacts_dir_atmos = joinpath (output_dir, mode_name_atmos, gpu_job_id_atmos) * " _artifacts"
116
- cpu_artifacts_dir_atmos = joinpath (output_dir, mode_name_atmos, cpu_job_id_atmos) * " _artifacts"
129
+ """
130
+ append_table_data(table_data, setup_id, cpu_job_id, gpu_job_id, cpu_artifacts_dir, gpu_artifacts_dir)
131
+
132
+ Append data for a given setup to the table data.
133
+ """
134
+ function append_table_data (table_data, setup_id, cpu_job_id, gpu_job_id, cpu_artifacts_dir, gpu_artifacts_dir)
135
+ # Get SYPD and allocation info for both input runs
136
+ cpu_sypd, cpu_max_rss = get_run_data (cpu_artifacts_dir)
137
+ gpu_sypd, gpu_cpu_max_rss = get_run_data (gpu_artifacts_dir)
138
+
139
+ # Create rows containing data for these runs
140
+ new_table_data = [
141
+ [" " " job ID:" cpu_job_id gpu_job_id]
142
+ [setup_id " SYPD:" cpu_sypd gpu_sypd]
143
+ [" " " CPU max RSS:" cpu_max_rss gpu_cpu_max_rss]
144
+ ]
145
+ return vcat (table_data, new_table_data)
146
+ end
117
147
118
- # Read in SYPD and allocations info from artifacts directories
119
- function get_sypd_allocs (artifacts_dir)
120
- # Read in SYPD info
121
- sypd_file = open (joinpath (artifacts_dir, " sypd.txt" ), " r" )
122
- sypd = round (parse (Float64, read (sypd_file, String)), digits = 4 )
123
148
124
- # Read in allocations info
125
- cpu_allocs_file = open ( joinpath (artifacts_dir, " allocations_cpu.txt " ), " r " )
126
- cpu_allocs = read (cpu_allocs_file, String)
149
+ # Read in command line arguments
150
+ parsed_args = ArgParse . parse_args ( ARGS , argparse_settings () )
151
+ output_dir = parsed_args[ " coupler_output_dir " ]
127
152
128
- return (sypd, cpu_allocs)
153
+ # Access buildkite pipeline ID (from `BUILDKITE_GITHUB_DEPLOYMENT_ID` variable)
154
+ build_id = parsed_args[" build_id" ]
155
+ if ! isnothing (build_id)
156
+ build_id_str = " Build ID: $build_id "
157
+ else
158
+ build_id_str = " Build ID: N/A"
129
159
end
130
160
131
- cpu_sypd_coupled, cpu_allocs_coupled = get_sypd_allocs (cpu_artifacts_dir_coupled)
132
- gpu_sypd_coupled, gpu_cpu_allocs_coupled = get_sypd_allocs (gpu_artifacts_dir_coupled )
133
- cpu_sypd_atmos, cpu_allocs_atmos = get_sypd_allocs (cpu_artifacts_dir_atmos )
134
- gpu_sypd_atmos, gpu_cpu_allocs_atmos = get_sypd_allocs (gpu_artifacts_dir_atmos )
161
+ # Read in run info for each of the cases we want to compare
162
+ run_info_coupled = get_run_info (parsed_args, " coupled " )
163
+ run_info_atmos_diagedmf = get_run_info (parsed_args, " atmos_diagedmf " )
164
+ run_info_atmos = get_run_info (parsed_args, " atmos " )
135
165
136
166
# Set up info for PrettyTables.jl
137
167
headers = [build_id_str, " Horiz. res.: 30 elems" , " CPU Run [64 processes]" , " GPU Run [4 A100s]" ]
138
168
data = [
139
169
[" " " Vert. res.: 63 levels" " " " " ]
140
170
[" " " dt: 120secs" " " " " ]
141
- [" " " job ID:" cpu_job_id_coupled gpu_job_id_coupled]
142
- [" Coupled" " SYPD:" cpu_sypd_coupled gpu_sypd_coupled]
143
- [" " " CPU max RSS allocs:" cpu_allocs_coupled gpu_cpu_allocs_coupled]
144
- [" " " job ID:" cpu_job_id_atmos gpu_job_id_atmos]
145
- [" Atmos-only" " SYPD:" cpu_sypd_atmos gpu_sypd_atmos]
146
- [" " " CPU max RSS allocs:" cpu_allocs_atmos gpu_cpu_allocs_atmos]
147
171
]
148
172
173
+ # Append data to the table for each of the cases we want to compare
174
+ data = append_table_data (data, " Coupled" , run_info_coupled... )
175
+ data = append_table_data (data, " Atmos with diag. EDMF" , run_info_atmos_diagedmf... )
176
+ data = append_table_data (data, " Atmos without diag. EDMF" , run_info_atmos... )
177
+
149
178
# Use the coupled CPU job ID for the output dir
150
- table_output_dir = joinpath (output_dir, " compare_$(mode_name) _$(mode_name_atmos) _$(cpu_job_id_coupled) " )
179
+ cpu_job_id_coupled = run_info_coupled[1 ]
180
+ table_output_dir = joinpath (output_dir, " compare_amip_climaatmos_$(cpu_job_id_coupled) " )
151
181
! isdir (table_output_dir) && mkdir (table_output_dir)
152
182
table_path = joinpath (table_output_dir, " table.txt" )
153
183
open (table_path, " w" ) do f
154
184
# Output the table, including lines before and after the header
155
- PrettyTables. pretty_table (f, data, header = headers, hlines = [0 , 3 , 6 , 9 ])
185
+ PrettyTables. pretty_table (f, data, header = headers, hlines = [0 , 3 , 6 , 9 , 12 ]) # TODO don't hardcode hlines
156
186
end
0 commit comments