SPH benchmark for homogeneous density box#

This example tests the the performance of the SPH solver for a homogeneous density box, the resolution is automatically adapted to the available memory and number of processes.

  9 import datetime
 10 import json
 11 import math
 12 from statistics import mean, stdev
 13
 14 import shamrock
 15
 16 device_properties = shamrock.sys.get_compute_device_properties()
 17
 18 microbench_results = shamrock.sys.get_microbench_results()
 19 if len(microbench_results) == 0:
 20     print("no microbench results, please run with --benchmark-mpi")
 21     raise ValueError("no microbench results")
 22
 23 memory_gb = device_properties["global_mem_size"] / (1e9)
 24
 25 N_target_base = 2 ** int(math.log2(memory_gb * 1e6 / 1.5))
 26 print(f"N_target_base = {N_target_base}")
 27 print(f"memory_gb = {memory_gb}")
 28 print(f"device_properties = {device_properties}")
 29
 30 N_target_base = min(N_target_base, 2**25)
 31
 32 if device_properties["type"] == "CPU":
 33     N_target_base = min(N_target_base, 2**23)
 34
 35 shamrock.backends.reset_mem_info_max()
 36
 37 gamma = 5.0 / 3.0
 38 rho_g = 1
 39 target_tot_u = 1
 40
 41 bmin = (-0.6, -0.6, -0.6)
 42 bmax = (0.6, 0.6, 0.6)
 43
 44 compute_multiplier = shamrock.sys.world_size()
 45 # compute_multiplier = 12
 46 scheduler_split_val = int(2e7)
 47 scheduler_merge_val = 1
 48
 49 N_target = N_target_base * compute_multiplier
 50 xm, ym, zm = bmin
 51 xM, yM, zM = bmax
 52 vol_b = (xM - xm) * (yM - ym) * (zM - zm)
 53
 54 if shamrock.sys.world_rank() == 0:
 55     print("N_target_base", N_target_base)
 56     print("compute_multiplier", compute_multiplier)
 57     print("scheduler_split_val", scheduler_split_val)
 58     print("scheduler_merge_val", scheduler_merge_val)
 59     print("N_target", N_target)
 60     print("vol_b", vol_b)
 61
 62 part_vol = vol_b / N_target
 63
 64 # lattice volume
 65 part_vol_lattice = 0.74 * part_vol
 66
 67 dr = (part_vol_lattice / ((4.0 / 3.0) * 3.1416)) ** (1.0 / 3.0)
 68
 69 pmass = -1
 70
 71 ctx = shamrock.Context()
 72 ctx.pdata_layout_new()
 73
 74 model = shamrock.get_Model_SPH(context=ctx, vector_type="f64_3", sph_kernel="M4")
 75
 76 cfg = model.gen_default_config()
 77 # cfg.set_artif_viscosity_Constant(alpha_u = 1, alpha_AV = 1, beta_AV = 2)
 78 # cfg.set_artif_viscosity_VaryingMM97(alpha_min = 0.1,alpha_max = 1,sigma_decay = 0.1, alpha_u = 1, beta_AV = 2)
 79 cfg.set_artif_viscosity_VaryingCD10(
 80     alpha_min=0.0, alpha_max=1, sigma_decay=0.1, alpha_u=1, beta_AV=2
 81 )
 82 cfg.set_boundary_periodic()
 83 cfg.set_eos_adiabatic(gamma)
 84 cfg.print_status()
 85 model.set_solver_config(cfg)
 86 model.init_scheduler(scheduler_split_val, scheduler_merge_val)
 87
 88 bmin, bmax = shamrock.math.get_ideal_hcp_box(dr, bmin, bmax)
 89 xm, ym, zm = bmin
 90 xM, yM, zM = bmax
 91
 92 model.resize_simulation_box(bmin, bmax)
 93
 94 setup = model.get_setup()
 95 gen = setup.make_generator_lattice_hcp(dr, bmin, bmax)
 96
 97 # Kind of optimized for Aurora
 98 setup.apply_setup(
 99     gen,
100     gen_step=int(scheduler_split_val / 8),
101     insert_step=int(scheduler_split_val * 2),
102     msg_count_limit=1024,
103     rank_comm_size_limit=int(scheduler_split_val) * 2,
104     max_msg_size=int(scheduler_split_val / 8),
105     do_setup_log=False,
106 )
107
108 xc, yc, zc = model.get_closest_part_to((0, 0, 0))
109
110 if shamrock.sys.world_rank() == 0:
111     print("closest part to (0,0,0) is in :", xc, yc, zc)
112
113 vol_b = (xM - xm) * (yM - ym) * (zM - zm)
114
115 totmass = rho_g * vol_b
116 # print("Total mass :", totmass)
117
118 pmass = model.total_mass_to_part_mass(totmass)
119
120 model.set_value_in_a_box("uint", "f64", 0, bmin, bmax)
121
122 rinj = 16 * dr
123 u_inj = 1
124 model.add_kernel_value("uint", "f64", u_inj, (0, 0, 0), rinj)
125
126 tot_u = pmass * model.get_sum("uint", "f64")
127 if shamrock.sys.world_rank() == 0:
128     print("total u :", tot_u)
129
130 # print("Current part mass :", pmass)
131 model.set_particle_mass(pmass)
132
133 model.set_cfl_cour(0.1)
134 model.set_cfl_force(0.1)
135
136 shamrock.backends.reset_mem_info_max()
137
138 # converge smoothing length and compute initial dt
139 model.timestep()
140
141 # Now run the actual benchmark for 5 steps
142 res_rates = []
143 res_cnts = []
144 res_system_metrics = []
145 res_mpi_timers = []
146
147 """
148 Here we insert callbacks to measure solver MPI usage by fetching the timers twice at the begining and end of the step
149 """
150 before_mpi_timers, after_mpi_timers = None, None
151
152
153 def callback_before_mpi_timer():
154     global before_mpi_timers
155     # print(shamrock.sys.world_rank(), "register before_mpi_timers")
156     before_mpi_timers = shamrock.comm.get_timers()
157
158
159 def callback_after_mpi_timer():
160     global after_mpi_timers
161     # print(shamrock.sys.world_rank(), "register after_mpi_timers")
162     after_mpi_timers = shamrock.comm.get_timers()
163
164
165 model.add_timestep_callback(step_begin=callback_before_mpi_timer, step_end=callback_after_mpi_timer)
166
167 for i in range(10):
168     if shamrock.sys.world_rank() == 0:
169         print("running step ", i + 1, "/", 10, " ...")
170
171     shamrock.sys.mpi_barrier()
172
173     # To replay the same step
174     model.set_next_dt(0.0)
175     model.timestep()
176
177     if shamrock.sys.world_rank() == 0:
178         print("collecting results ...")
179
180     tmp_res_rate, tmp_res_cnt, tmp_system_metrics = (
181         model.solver_logs_last_rate(),
182         model.solver_logs_last_obj_count(),
183         model.solver_logs_last_system_metrics(),
184     )
185     res_rates.append(tmp_res_rate)
186     res_cnts.append(tmp_res_cnt)
187     res_system_metrics.append(tmp_system_metrics)
188     res_mpi_timers.append(shamrock.comm.mpi_timers_delta(before_mpi_timers, after_mpi_timers))
189
190     if shamrock.sys.world_rank() == 0:
191         print("sleeping 1 second ...")
192
193     import time
194
195     time.sleep(1)
196
197     if shamrock.sys.world_rank() == 0:
198         print("done sleeping 1 second ...")
199
200 # result is the best rate of the 5 steps
201 res_rate, res_cnt = max(res_rates), res_cnts[0]
202
203 # index of the max rate
204 max_rate_index = res_rates.index(max(res_rates))
205 max_rate_system_metrics = res_system_metrics[max_rate_index]
206 max_mpi_timers = res_mpi_timers[max_rate_index]
207 step_time = res_cnt / res_rate
208
209 if shamrock.sys.world_rank() == 0:
210     result_text = ""
211     result_text += f"--- final score for N_target_base={N_target_base} ---"
212     result_text += f"world size  : {shamrock.sys.world_size()}\n"
213     result_text += f"result rate : {res_rate}\n"
214     result_text += f"result cnt  : {res_cnt}\n"
215     result_text += f"cnt/rank    : {res_cnt / shamrock.sys.world_size()}\n"
216     result_text += f"result rate per rank : {res_rate / shamrock.sys.world_size()}\n"
217     result_text += f"rates infos : max={max(res_rates)}, min={min(res_rates)}, mean={mean(res_rates)}, stddev={stdev(res_rates)}\n"
218     result_text += f"res_rates = {res_rates}\n"
219     result_text += f"res_cnts = {res_cnts}\n"
220     result_text += f"step time = {step_time}\n"
221
222     dic_out = {
223         "device_properties": device_properties,
224         "microbench_results": shamrock.sys.get_microbench_results(),
225         "shamrock_version": shamrock.version_string(),
226         "shamrock_compiler_id_string": shamrock.get_compiler_id_string(),
227         "shamrock_compile_flags": shamrock.get_compile_arg(),
228         "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
229         "world_size": shamrock.sys.world_size(),
230         "rate": res_rate,
231         "cnt": res_cnt,
232         "step_time": step_time,
233         "mpi_timers": max_mpi_timers,
234     }
235
236     # print the system metrics
237     metrics_duration = max_rate_system_metrics["duration"]
238     result_text += "system metrics:\n"
239     for key, value in max_rate_system_metrics.items():
240         if not key == "duration":
241             result_text += f"{key}: {value} J\n"
242             dic_out[key] = value
243
244     for key, value in max_rate_system_metrics.items():
245         if not key == "duration":
246             result_text += f"avg power {key} / step time : {value / metrics_duration} W\n"
247             dic_out[f"power_{key}"] = value / metrics_duration
248
249     dic_out["system_metric_duration"] = metrics_duration
250
251     result_text += "---------submit this result--------\n"
252     result_text += f"{json.dumps(dic_out, indent=4)}\n"
253     result_text += "-----------------------------------\n"
254
255     print("current results:")
256     print(result_text)

Estimated memory usage: 0 MB

Gallery generated by Sphinx-Gallery