Skip to content

Commit 07a5f8f

Browse files
Merge pull request #308 from casparvl/lbmpy-pssrt
Add lbmpy-pssrt test
2 parents a4a41b3 + b005ac8 commit 07a5f8f

File tree

4 files changed

+431
-0
lines changed

4 files changed

+431
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# WARNING: do not remove this file.
2+
# It is needed to autogenerate documentation from this repo.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
This module tests an lbmpy fork twith additional functionality added within the MultiXscale project.
3+
Long term, the goal is that this will be upstreamed in lbmpy.
4+
"""
5+
6+
import reframe as rfm
7+
import reframe.utility.sanity as sn
8+
9+
# added only to make the linter happy
10+
from reframe.core.builtins import parameter, performance_function, sanity_function, deferrable, run_after
11+
12+
# Import the EESSI_Mixin class so that we can inherit from it
13+
from eessi.testsuite.eessi_mixin import EESSI_Mixin
14+
from eessi.testsuite.constants import COMPUTE_UNITS, DEVICE_TYPES, SCALES
15+
from eessi.testsuite.utils import find_modules
16+
from eessi.testsuite.hooks import set_compact_thread_binding
17+
18+
19+
def filter_singlenode_scales():
20+
"""
21+
Filtering function that returns only single node scales.
22+
"""
23+
return [k for (k, v) in SCALES.items() if v['num_nodes'] == 1]
24+
25+
26+
@rfm.simple_test
27+
class EESSI_lbmpy_pssrt(rfm.RunOnlyRegressionTest, EESSI_Mixin):
28+
"""
29+
This test case simulates the Kelvin-Helmholtz instabilty where an initial hyperbolic tangent velocity profile
30+
imposed in a fully periodic 2D square box is slightly perturbed to initiate rolling of the shear layers.
31+
32+
This use case tests a modified version of lbmpy, with additional functionality. This test cases uses lbmpy with
33+
OpenMP parallelization. As such, this test will only be instantiated on scales up to 1 full node.
34+
The runtime is in the order of seconds to minutes.
35+
36+
The test script takes three (optional) arguments: --grid-size, --run-time, --openmp.
37+
If grid-size or run-time are modified, the reference value in the assert_normalized_average_kinetic_energy sanity
38+
check needs to be updated. The reference does _not_ change with the number of threads.
39+
"""
40+
41+
# lbmpy-pssrt is only parallelized with OpenMP, so no multi-node tests should be ran
42+
scale = parameter(filter_singlenode_scales())
43+
44+
device_type = DEVICE_TYPES.CPU
45+
46+
# lbmpy-pssrt is only OpenMP parallel, so launch only one task on a node
47+
compute_unit = COMPUTE_UNITS.NODE
48+
49+
launcher = 'local' # no MPI module is loaded in this test
50+
51+
module_name = parameter(find_modules('lbmpy-pssrt'))
52+
53+
readonly_files = ['mixing_layer_2D.py']
54+
55+
executable = 'python'
56+
# grid-size of 512 seems to scale reasonable to 128 cores, and completes in reasonable time on one core (< 2 mins)
57+
executable_opts = ['mixing_layer_2D.py', '--grid-size 512'] # 512 seems to scale _reasonable_ to 128 cores
58+
time_limit = '10m00s'
59+
60+
is_ci_test = True
61+
62+
perf_regex = r'^\s+Median±\(max-min\)\s+=\s+(?P<perf>\S+)±(?P<perf_range>\S+)\s+MLUPS'
63+
64+
def required_mem_per_node(self):
65+
"""
66+
Defines the required memory per node to run this test
67+
"""
68+
return self.num_cpus_per_task * 5 + 250
69+
70+
@deferrable
71+
def assert_normalized_average_kinetic_energy(self):
72+
"""
73+
Assert that the normalized average kinetic energy matches the reference (exactly).
74+
Note that the reference needs to be adjusted if a different --grid-size or --run-time is used.
75+
It should, however, be robust against changes in the number of threads.
76+
"""
77+
regex = r"Normalized Average Kinetic Energy\s+=\s+(?P<energy>\S+)"
78+
energy = sn.extractsingle(regex, self.stdout, 'energy', float)
79+
ref_energy = 0.9381
80+
return sn.assert_eq(energy, ref_energy)
81+
82+
@sanity_function
83+
def validate(self):
84+
"""
85+
This is the sanity function for this test. Currently, it only checks that
86+
assert_normalized_average_kinetic_energy is true, but this may be expanded with additional sanity checking
87+
if needed.
88+
"""
89+
return sn.assert_true(self.assert_normalized_average_kinetic_energy())
90+
91+
@performance_function('MLU/s')
92+
def lattice_updates(self):
93+
"""
94+
This test case reports number of Mega lattice updates per second (and a range) over 5 iterations.
95+
"""
96+
return sn.extractsingle(self.perf_regex, self.stdout, 'perf', float)
97+
98+
@performance_function('MLU/s')
99+
def lattice_updates_range(self):
100+
"""
101+
This test case reports range (max-min) of number of Mega lattice updates per second, over 5 iterations.
102+
In other words, it takes the difference in Mega lattice updates per seconds between the slowest and the
103+
fastest iteration
104+
"""
105+
return sn.extractsingle(self.perf_regex, self.stdout, 'perf_range', float)
106+
107+
@run_after('setup')
108+
def set_openmp_argument(self):
109+
"""
110+
If the number of cpus_per_task is larger than 1, enable OpenMP by setting the --openmp argument.
111+
Also, set compact thread binding in this case
112+
"""
113+
if self.num_cpus_per_task > 1:
114+
self.executable_opts += ['--openmp']
115+
set_compact_thread_binding(self)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# WARNING: do not remove this file.
2+
# It is needed to autogenerate documentation from this repo.

0 commit comments

Comments
 (0)