Skip to content

Commit 03033c4

Browse files
PackInfo code generation (#4994)
Fixes #4921 Description of changes: - reduce volume of the LB communication during the streaming step - avoid superfluous LB ghost communication outside the streaming step - use AVX streaming kernels
2 parents 9527087 + 960c2ad commit 03033c4

35 files changed

Lines changed: 3906 additions & 48 deletions

maintainer/benchmarks/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,5 @@ add_custom_target(
150150
COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${ESPRESSO_TEST_TIMEOUT}
151151
${ESPRESSO_CTEST_ARGS} --output-on-failure)
152152

153-
add_dependencies(benchmark benchmark_python benchmarks_data)
153+
add_dependencies(benchmark_python pypresso benchmarks_data)
154+
add_dependencies(benchmark benchmark_python)

maintainer/benchmarks/benchmarks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def get_timings(system, n_steps, n_iterations, verbose=True):
8484
energy = system.analysis.energy()["total"]
8585
verlet = system.cell_system.get_state()["verlet_reuse"]
8686
print(
87-
f"step {i}, time: {1000 * t:.1f} ms, verlet: {verlet:.2f}, energy: {energy:.2e}")
87+
f"step {i}, time: {1000 * t:.2f} ms, verlet: {verlet:.2f}, energy: {energy:.2e}")
8888
return np.array(timings)
8989

9090

maintainer/benchmarks/lb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149

150150
# average time
151151
avg, ci = benchmarks.get_average_time(timings)
152-
print(f"average: {1000 * avg:.1f} +/- {1000 * ci:.1f} ms (95% C.I.)")
152+
print(f"average: {1000 * avg:.2f} +/- {1000 * ci:.2f} ms (95% C.I.)")
153153

154154
# write report
155155
benchmarks.write_report(args.output, n_proc, timings, measurement_steps)

maintainer/walberla_kernels/generate_lb_kernels.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ def paramlist(parameters, keys):
9898
stencil = lbmpy.stencils.LBStencil(lbmpy.enums.Stencil.D3Q19)
9999
fields = pystencils_espresso.generate_fields(config, stencil)
100100
force_field = fields["force"]
101+
lbm_opt = lbmpy.LBMOptimisation(symbolic_field=fields["pdfs"])
102+
streaming_pattern = "push"
101103

102104
# LB Method definition
103105
method = lbmpy.creationfunctions.create_mrt_orthogonal(
@@ -133,12 +135,11 @@ def paramlist(parameters, keys):
133135
force_model=lbmpy.ForceModel.GUO,
134136
force=force_field.center_vector,
135137
kernel_type="collide_only")
136-
lbm_opt = lbmpy.LBMOptimisation(symbolic_field=fields["pdfs"])
137-
le_collision_rule_unthermalized = lbmpy.create_lb_update_rule(
138+
le_update_rule_unthermalized = lbmpy.create_lb_update_rule(
138139
lbm_config=le_config,
139140
lbm_optimisation=lbm_opt)
140141
le_collision_rule_unthermalized = lees_edwards.add_lees_edwards_to_collision(
141-
config, le_collision_rule_unthermalized,
142+
config, le_update_rule_unthermalized,
142143
fields["pdfs"], stencil, 1) # shear_dir_normal y
143144
for params, target_suffix in paramlist(parameters, ("GPU", "CPU", "AVX")):
144145
pystencils_espresso.generate_collision_sweep(
@@ -153,8 +154,8 @@ def paramlist(parameters, keys):
153154
ps.TypedSymbol(f"block_offset_{i}", np.uint32)
154155
for i in range(3))
155156

156-
# generate thermalized LB
157-
collision_rule_thermalized = lbmpy.creationfunctions.create_lb_collision_rule(
157+
# generate thermalized LB collision rule
158+
lb_collision_rule_thermalized = lbmpy.creationfunctions.create_lb_collision_rule(
158159
method,
159160
zero_centered=False,
160161
fluctuating={
@@ -170,7 +171,7 @@ def paramlist(parameters, keys):
170171
pystencils_espresso.generate_collision_sweep(
171172
ctx,
172173
method,
173-
collision_rule_thermalized,
174+
lb_collision_rule_thermalized,
174175
stem,
175176
params,
176177
block_offset=block_offsets,
@@ -192,6 +193,30 @@ def paramlist(parameters, keys):
192193
ctx, config, method, templates
193194
)
194195

196+
# generate PackInfo
197+
assignments = pystencils_espresso.generate_pack_info_pdfs_field_assignments(
198+
fields, streaming_pattern="pull")
199+
spec = pystencils_espresso.generate_pack_info_vector_field_specifications(
200+
config, stencil, force_field.layout)
201+
for params, target_suffix in paramlist(parameters, ["CPU"]):
202+
pystencils_walberla.generate_pack_info_from_kernel(
203+
ctx, f"PackInfoPdf{precision_prefix}{target_suffix}", assignments,
204+
kind="pull", **params)
205+
pystencils_walberla.generate_pack_info(
206+
ctx, f"PackInfoVec{precision_prefix}{target_suffix}", spec, **params)
207+
if target_suffix == "CUDA":
208+
continue
209+
token = "\n //TODO: optimize by generating kernel for this case\n"
210+
for field_suffix in ["Pdf", "Vec"]:
211+
class_name = f"PackInfo{field_suffix}{precision_prefix}{target_suffix}" # nopep8
212+
with open(f"{class_name}.h", "r+") as f:
213+
content = f.read()
214+
assert token in content
215+
content = content.replace(token, "\n")
216+
f.seek(0)
217+
f.truncate()
218+
f.write(content)
219+
195220
# boundary conditions
196221
ubb_dynamic = lbmpy_espresso.UBB(
197222
lambda *args: None, dim=3, data_type=config.data_type.default_factory())
@@ -202,7 +227,7 @@ def paramlist(parameters, keys):
202227
lbmpy_walberla.generate_boundary(
203228
ctx, f"Dynamic_UBB_{precision_suffix}{target_suffix}", ubb_dynamic,
204229
method, additional_data_handler=ubb_data_handler,
205-
streaming_pattern="push", target=target)
230+
streaming_pattern=streaming_pattern, target=target)
206231

207232
with open(f"Dynamic_UBB_{precision_suffix}{target_suffix}.h", "r+") as f:
208233
content = f.read()

maintainer/walberla_kernels/pystencils_espresso.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,8 @@ def __init__(self, dim, time_step=ps.typing.TypedSymbol(
164164
data_type_np = {'double': 'float64', 'float': 'float32'}
165165

166166

167-
def generate_fields(config, stencil):
167+
def generate_fields(config, stencil, field_layout='fzyx'):
168168
dtype = data_type_np[config.data_type.default_factory().c_name]
169-
field_layout = 'fzyx'
170169
q = len(stencil)
171170
dim = len(stencil[0])
172171

@@ -208,6 +207,60 @@ def generate_fields(config, stencil):
208207
return fields
209208

210209

210+
def generate_pack_info_pdfs_field_assignments(fields, streaming_pattern):
211+
"""
212+
Visualize the stencil directions with::
213+
214+
import lbmpy
215+
import matplotlib.pyplot as plt
216+
stencil = lbmpy.LBStencil(lbmpy.Stencil.D3Q19)
217+
stencil.plot(data=[i for i in range(19)])
218+
plt.show()
219+
220+
"""
221+
stencil = lbmpy.enums.Stencil.D3Q19
222+
lbm_config = lbmpy.LBMConfig(stencil=stencil,
223+
method=lbmpy.Method.CUMULANT,
224+
compressible=True,
225+
zero_centered=False,
226+
weighted=True,
227+
streaming_pattern=streaming_pattern,
228+
relaxation_rate=sp.Symbol("omega_shear"),
229+
)
230+
lbm_opt = lbmpy.LBMOptimisation(
231+
symbolic_field=fields["pdfs" if streaming_pattern ==
232+
"pull" else "pdfs_tmp"],
233+
symbolic_temporary_field=fields["pdfs" if streaming_pattern ==
234+
"push" else "pdfs_tmp"],
235+
field_layout=fields['pdfs'].layout)
236+
lbm_update_rule = lbmpy.create_lb_update_rule(
237+
lbm_config=lbm_config,
238+
lbm_optimisation=lbm_opt)
239+
return lbm_update_rule.all_assignments
240+
241+
242+
def generate_pack_info_vector_field_specifications(config, stencil, layout):
243+
import collections
244+
import itertools
245+
field = ps.Field.create_generic(
246+
"field",
247+
3,
248+
data_type_np[config.data_type.default_factory().c_name],
249+
index_dimensions=1,
250+
layout=layout,
251+
index_shape=(3,)
252+
)
253+
q = len(stencil)
254+
coord = itertools.product(*[(-1, 0, 1)] * 3)
255+
if q == 19:
256+
dirs = tuple((i, j, k) for i, j, k in coord if i**2 + j**2 + k**2 != 3)
257+
else:
258+
dirs = tuple((i, j, k) for i, j, k in coord)
259+
spec = collections.defaultdict(set)
260+
spec[dirs] = {field[0, 0, 0](i) for i in range(3)}
261+
return spec
262+
263+
211264
def generate_config(ctx, params):
212265
return pystencils_walberla.utility.config_from_context(ctx, **params)
213266

src/core/integrate.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ int System::System::integrate(int n_steps, int reuse_forces) {
629629
propagation.lb_skipped_md_steps = 0;
630630
propagation.ek_skipped_md_steps = 0;
631631
lb.propagate();
632+
lb.ghost_communication_vel();
632633
ek.propagate();
633634
}
634635
} else if (lb_active) {
@@ -654,6 +655,9 @@ int System::System::integrate(int n_steps, int reuse_forces) {
654655
#ifdef VIRTUAL_SITES_INERTIALESS_TRACERS
655656
if (thermostat->lb and
656657
(propagation.used_propagations & PropagationMode::TRANS_LB_TRACER)) {
658+
if (lb_active) {
659+
lb.ghost_communication_vel();
660+
}
657661
lb_tracers_propagate(*cell_structure, lb, time_step);
658662
}
659663
#endif
@@ -678,6 +682,9 @@ int System::System::integrate(int n_steps, int reuse_forces) {
678682
}
679683

680684
} // for-loop over integration steps
685+
if (lb_active) {
686+
lb.ghost_communication();
687+
}
681688
lees_edwards->update_box_params(*box_geo, sim_time);
682689
#ifdef CALIPER
683690
CALI_CXX_MARK_LOOP_END(integration_loop);

src/core/lb/LBNone.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ namespace LB {
2929

3030
struct LBNone {
3131
void propagate() { throw NoLBActive{}; }
32+
void ghost_communication() { throw NoLBActive{}; }
33+
void ghost_communication_pdf() { throw NoLBActive{}; }
34+
void ghost_communication_vel() { throw NoLBActive{}; }
3235
double get_agrid() const { throw NoLBActive{}; }
3336
double get_tau() const { throw NoLBActive{}; }
3437
double get_kT() const { throw NoLBActive{}; }

src/core/lb/LBWalberla.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ Utils::VectorXd<9> LBWalberla::get_pressure_tensor() const {
5252

5353
void LBWalberla::propagate() { lb_fluid->integrate(); }
5454

55+
void LBWalberla::ghost_communication() { lb_fluid->ghost_communication(); }
56+
57+
void LBWalberla::ghost_communication_pdf() {
58+
lb_fluid->ghost_communication_vel();
59+
}
60+
61+
void LBWalberla::ghost_communication_vel() {
62+
lb_fluid->ghost_communication_vel();
63+
}
64+
5565
void LBWalberla::lebc_sanity_checks(unsigned int shear_direction,
5666
unsigned int shear_plane_normal) const {
5767
lb_fluid->check_lebc(shear_direction, shear_plane_normal);

src/core/lb/LBWalberla.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ struct LBWalberla {
7272
std::vector<Utils::Vector3d>
7373
get_velocities_at_pos(std::vector<Utils::Vector3d> const &pos);
7474
void propagate();
75+
void ghost_communication();
76+
void ghost_communication_pdf();
77+
void ghost_communication_vel();
7578
void veto_time_step(double time_step) const;
7679
void veto_kT(double kT) const;
7780
void sanity_checks(System::System const &system) const;

src/core/lb/Solver.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,21 @@ void Solver::propagate() {
7373
std::visit([](auto &ptr) { ptr->propagate(); }, *impl->solver);
7474
}
7575

76+
void Solver::ghost_communication() {
77+
check_solver(impl);
78+
std::visit([](auto &ptr) { ptr->ghost_communication(); }, *impl->solver);
79+
}
80+
81+
void Solver::ghost_communication_pdf() {
82+
check_solver(impl);
83+
std::visit([](auto &ptr) { ptr->ghost_communication_pdf(); }, *impl->solver);
84+
}
85+
86+
void Solver::ghost_communication_vel() {
87+
check_solver(impl);
88+
std::visit([](auto &ptr) { ptr->ghost_communication_vel(); }, *impl->solver);
89+
}
90+
7691
void Solver::sanity_checks() const {
7792
if (impl->solver) {
7893
auto const &system = get_system();

0 commit comments

Comments
 (0)