Peano
Loading...
Searching...
No Matches
plot_celldepth_benchmarks.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3# --------------------------------------------------------------------------
4# Plot results of cell depth benchmarks.
5# Expects outputs with the file name format
6#
7# output_N$N_PART-$CELL_MAX-$CELL_MIN.log
8#
9# as written by `run_celldepth_test.sh`.
10# The content of that output shall be the peano exaparty stdout, with the
11# addition of an external timer run as such (using bash):
12#
13# timing() {
14#
15# timeformat="----------------------------------------------------------------\n"
16# timeformat="$timeformat""stats for %C\n"
17# timeformat="$timeformat""AverageMem(kb),MaxMem(kb),WallTime(s),CPUTime(s),UserTime(s),CPUPercentage\n"
18# timeformat="$timeformat""%K,%M,%e,%S,%U,%P"
19#
20# /usr/bin/time -f "$timeformat" "$@"
21# }
22#
23# OUTFILE=output_N$N_PART-$CELL_MAX-$CELL_MIN.log
24# timing -o "$OUTFILE" -a ./noh2D-$SUFFIX 2>&1 > "$OUTFILE"
25#
26# --------------------------------------------------------------------------
27
28
29from matplotlib import pyplot as plt
30import os
31import argparse
32
33
35 """
36 Find all log files
37 """
38
39 ls = os.listdir()
40 logfiles = []
41
42 for f in ls:
43 if f.startswith("output_N") and f.endswith(".log"):
44 logfiles.append(f)
45
46 if len(logfiles) == 0:
47 raise ValueError("No log files found. Directory contents:", ls)
48
49 return logfiles
50
51
53 def __init__(self, file):
54 """
55 Pass a valid filename to a logfile.
56 It will extract benchmark timing data.
57 """
58
59 self.file = file
60
61 self.npart = 0
62 self.cellmax = 0.0
63 self.cellmin = 0.0
64
65 self.walltime = 0.0
66 self.maxmem = 0.0
67 self.CPUPercentage = 0.0
68
71 self.initialisation = 0.0
72 self.plotting = 0.0
73 self.cleanup = 0.0
74 self.timestepping = 0.0
75
76 self._read_logfile()
77
78 def print(self):
79 print("----------------------------------------------------------")
80 print(f"file= {self.file}")
81 print(f"npart= {self.npart}")
82 print(f"cell_min= {self.cellmin}")
83 print(f"cell_max= {self.cellmax}")
84
85 print(f"walltime= {self.walltime} (s)")
86 print(f"max memory= {self.maxmem} (kB)")
87 print(f"CPU Percentage= {self.CPUPercentage} %")
88
89 print(f"grid construction= {self.grid_construction} (s)")
90 print(f"initial conditions= {self.initial_conditions} (s)")
91 print(f"initialisation= {self.initialisation} (s)")
92 print(f"plotting= {self.plotting} (s)")
93 print(f"cleanup= {self.cleanup} (s)")
94 print(f"timestepping= {self.timestepping} (s)")
95 print("----------------------------------------------------------")
96
97 def _read_logfile(self):
98 """
99 Extract data from a logfile.
100 """
101
102 # First meta-data from filename.
103
104 rawfilename = self.file.strip(".log")
105 rawfilename = rawfilename.strip("output_")
106
107 n, cmax, cmin = rawfilename.split("-")
108 self.npart = int(n.strip("N"))
109 self.cellmax = float(cmax)
110 self.cellmin = float(cmin)
111
112 f = open(self.file, "r")
113 lines = f.readlines()
114 timing = lines[-1]
115 timing = timing.strip()
116 avmem, maxmem, walltime, cputime, usertime, cpupercent = timing.split(",")
117
118 self.maxmem = float(maxmem)
119 self.walltime = float(walltime)
120 self.CPUPercentage = float(cpupercent.strip("%"))
121
122 termline = lines[-11]
123 tl = termline.strip()
124 # remove all whitespace, then join together with a single whitespace
125 tl = " ".join(tl.split())
126 _, _, _, _, _, _, terminated, successfully = tl.split()
127 if terminated != "terminated" or successfully != "successfully":
128 raise ValueError("Reading wrong 'terminated successfully' line:", termline)
129
130 gridline = lines[-10]
131 gl = gridline.strip()
132 gl = " ".join(gl.split())
133 _, _, _, _, _, _, grid, construction, timing, _, _, _ = gl.split()
134 if grid != "grid" or construction != "construction:":
135 raise ValueError("Reading wrong 'grid construction' line", gridline)
136 gridtime = float(timing.strip("s"))
137 self.grid_construction = gridtime
138
139 icline = lines[-9]
140 icl = icline.strip()
141 icl = " ".join(icl.split())
142 _, _, _, _, _, _, initial, conditions, timing, _, _, _ = icl.split()
143 if initial != "initial" or conditions != "conditions:":
144 raise ValueError("Reading wrong 'initial conditions' line", icline)
145 ictime = float(timing.strip("s"))
146 self.initial_conditions = ictime
147
148 initline = lines[-8]
149 il = initline.strip()
150 il = " ".join(il.split())
151 _, _, _, _, _, _, initialisation, timing, _, _, _ = il.split()
152 if initialisation != "initialisation:":
153 raise ValueError("Reading wrong 'initialalisation' line", initline)
154 inittime = float(timing.strip("s"))
155 self.initialisation = inittime
156
157 plotline = lines[-7]
158 pl = plotline.strip()
159 pl = " ".join(pl.split())
160 _, _, _, _, _, _, plotting, timing, _, _, _ = pl.split()
161 if plotting != "plotting:":
162 raise ValueError("Reading wrong 'plotting' line", plotline)
163 plottime = float(timing.strip("s"))
164 self.plotting = plottime
165
166 cleanup = lines[-6]
167 cl = cleanup.strip()
168 cl = " ".join(cl.split())
169 _, _, _, _, _, _, cleanup, timing, _, _, _ = cl.split()
170 if cleanup != "cleanup:":
171 raise ValueError("Reading wrong 'cleanup' line", cleanup)
172 cleantime = float(timing.strip("s"))
173 self.cleanup = cleantime
174
175 timestepping = lines[-5]
176 tl = timestepping.strip()
177 tl = " ".join(tl.split())
178 _, _, _, _, _, _, time, stepping, timing, _, _, _ = tl.split()
179 if time != "time" and stepping != "stepping:":
180 raise ValueError("Reading wrong 'time stepping' line", timestepping)
181 tstime = float(timing.strip("s"))
182 self.timestepping = tstime
183
184 f.close()
185
186 return
187
188
189parser = argparse.ArgumentParser(description="Plot benchmark outputs.")
190parser.add_argument(
191 "-l",
192 "--log",
193 dest="log",
194 action="store_true",
195 default=False,
196 help="Plot log scale",
197)
198parser.add_argument(
199 "-b",
200 "--both",
201 dest="both",
202 action="store_true",
203 default=False,
204 help="Plot lin and log scale",
205)
206args = parser.parse_args()
207
208log = args.log
209both = args.both
210
211
212logfiles = get_all_logs()
213alldata = [BenchmarkData(l) for l in logfiles]
214
215# find all N_PART available
216npartlist = []
217for d in alldata:
218 if d.npart not in npartlist:
219 npartlist.append(d.npart)
220
221
222data_by_npart = []
223
224for n in npartlist:
225 templist = []
226 for d in alldata:
227 if d.npart == n:
228 templist.append(d)
229
230 # Sort the individual list by CELL_MAX/CELL_MIN
231 sort_val_list = [t.cellmax * 1e3 + t.cellmin for t in templist]
232
233 sort_val_list, templist = (
234 list(t) for t in zip(*sorted(zip(sort_val_list, templist)))
235 )
236 templist = templist[::-1] # invert sorting
237
238 data_by_npart.append(templist)
239
240
241if both:
242 fig = plt.figure(figsize=(24, 6), dpi=300)
243 ax1 = fig.add_subplot(1, 2, 1)
244 ax2 = fig.add_subplot(1, 2, 2)
245else:
246 fig = plt.figure(figsize=(12, 6), dpi=300)
247 ax = fig.add_subplot(1, 1, 1)
248
249markers = ["s", "o", "^", "<", ">"]
250
251for n, npart in enumerate(npartlist):
252 data = data_by_npart[n]
253
254 xvals = [str(d.cellmax) + "/" + str(d.cellmin) for d in data]
255 walltimes = [d.walltime for d in data]
256 timestepping = [d.timestepping for d in data]
257
258 if both:
259 ax1.plot(
260 xvals,
261 walltimes,
262 marker=markers[n],
263 label="walltime " + str(npart) + r"$^2$",
264 linestyle="-",
265 c="C" + str(n),
266 )
267 ax1.plot(
268 xvals,
269 timestepping,
270 marker=markers[n],
271 label="timestepping " + str(npart) + r"$^2$",
272 linestyle="--",
273 c="C" + str(n),
274 )
275
276 ax2.semilogy(
277 xvals,
278 walltimes,
279 marker=markers[n],
280 label="walltime " + str(npart) + r"$^2$",
281 linestyle="-",
282 c="C" + str(n),
283 )
284 ax2.semilogy(
285 xvals,
286 timestepping,
287 marker=markers[n],
288 label="timestepping " + str(npart) + r"$^2$",
289 linestyle="--",
290 c="C" + str(n),
291 )
292
293 else:
294 if log:
295 ax.semilogy(
296 xvals,
297 walltimes,
298 marker=markers[n],
299 label="walltime " + str(npart) + r"$^2$",
300 linestyle="-",
301 c="C" + str(n),
302 )
303 ax.semilogy(
304 xvals,
305 timestepping,
306 marker=markers[n],
307 label="timestepping " + str(npart) + r"$^2$",
308 linestyle="--",
309 c="C" + str(n),
310 )
311 else:
312 ax.plot(
313 xvals,
314 walltimes,
315 marker=markers[n],
316 label="walltime " + str(npart) + r"$^2$",
317 linestyle="-",
318 c="C" + str(n),
319 )
320 ax.plot(
321 xvals,
322 timestepping,
323 marker=markers[n],
324 label="timestepping " + str(npart) + r"$^2$",
325 linestyle="--",
326 c="C" + str(n),
327 )
328
329if both:
330 for ax in [ax1, ax2]:
331 ax.set_xlabel("cell_size_max/cell_size_min")
332 ax.set_ylabel("time (s)")
333 ax.legend()
334else:
335 ax.set_xlabel("cell_size_max/cell_size_min")
336 ax.set_ylabel("time (s)")
337 ax.legend()
338
339suffix = ""
340if log:
341 suffix = "-log"
342if both:
343 suffix = "-lin-log"
344fname = "celldepth_benchmark" + suffix + ".png"
345
346plt.tight_layout()
347# plt.show()
348plt.savefig(fname)
349print("Saved", fname)
_read_logfile(self)
Extract data from a logfile.
__init__(self, file)
Pass a valid filename to a logfile.