Skip to content

Commit 18d5895

Browse files
Add Missing Helper from Refactor and Cleanup Logic (#1265)
* Add get_spack_variants back * Simplify class and checks. Only add spack variant if defined. Only define variant if used by experiment * Simplify checks since error will be caught by spec logic
1 parent e2f3670 commit 18d5895

File tree

3 files changed

+52
-44
lines changed

3 files changed

+52
-44
lines changed

lib/benchpark/experiment.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -255,34 +255,22 @@ def __init__(self, spec):
255255

256256
self.package_specs = {}
257257

258-
# Set available programming models for checks
259-
models = set()
260-
for cls in self.__class__.mro():
261-
models.update(getattr(cls, "_available_programming_models", ()))
262-
self.programming_models = list(models)
258+
# Get available programming models for checks
259+
self.programming_models = list(self._available_programming_models)
263260

264261
# Explicitly ordered list. "mpi" first
265262
models = ["mpi"] + ["openmp", "cuda", "rocm"]
266-
valid_models = []
267-
invalid_models = []
268-
for model in models:
269-
if self.spec.satisfies("+" + model):
270-
valid_models.append(model)
271-
# Experiment specifying model in add_package_spec that it doesn't implement
272-
if model not in self.programming_models:
273-
invalid_models.append(model)
274-
# MPI is always valid if with another programming model, even if no mpionly
275-
if "mpi" in invalid_models and len(valid_models) > 1:
276-
invalid_models.remove("mpi")
277263
# Case where there are no experiments specified in experiment.py
278264
if len(self.programming_models) == 0:
279265
raise BenchparkError(
280266
f"Please specify a programming model in your {self.name}/experiment.py (e.g. ProgrammingModelType.Mpionly, ProgrammingModelType.Openmp, ProgrammingModelType.Cuda, ProgrammingModelType.Rocm). See other experiments for examples."
281267
)
282-
elif len(invalid_models) > 0:
283-
print(self.spec)
268+
# Check if experiment is trying to run in MpiOnly mode without being an ProgrammingModelType.Mpionly experiment
269+
elif "mpi" not in str(self.spec) and not any(
270+
self.spec.satisfies("+" + model) for model in models[1:]
271+
):
284272
raise BenchparkError(
285-
f'{invalid_models} are not valid programming models for "{self.name}". Choose from {self.programming_models}.'
273+
f'"{self.name}" cannot run with MPI only without inheriting from ProgrammingModelType.Mpionly. Choose from {self.programming_models}'
286274
)
287275

288276
if (

lib/benchpark/programming_model.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,23 @@ def ProgrammingModel(*types):
2525
# Normalize once so we can reuse
2626
_available = tuple(t.value for t in types)
2727

28-
class BaseModel:
29-
requires("mpi", when="+mpi")
30-
requires("rocm", when="+rocm")
31-
requires("cuda", when="+cuda")
32-
requires("openmp", when="+openmp")
28+
@staticmethod
29+
def is_available(mod):
30+
return mod in _available
3331

34-
variant("mpi", default=True, description="Run with MPI")
35-
variant("rocm", default=False, description="Build and run with ROCm")
36-
variant("cuda", default=False, description="Build and run with CUDA")
37-
variant("openmp", default=False, description="Build and run with OpenMP")
32+
class BaseModel:
33+
if "mpi" in _available:
34+
requires("mpi", when="+mpi")
35+
variant("mpi", default=True, description="Run with MPI")
36+
if "rocm" in _available:
37+
requires("rocm", when="+rocm")
38+
variant("rocm", default=False, description="Build and run with ROCm")
39+
if "cuda" in _available:
40+
requires("cuda", when="+cuda")
41+
variant("cuda", default=False, description="Build and run with CUDA")
42+
if "openmp" in _available:
43+
requires("openmp", when="+openmp")
44+
variant("openmp", default=False, description="Build and run with OpenMP")
3845

3946
# Class-level list of supported models for any class that includes this mixin
4047
_available_programming_models = _available
@@ -48,12 +55,7 @@ def available_programming_models(self):
4855
models.update(getattr(cls, "_available_programming_models", ()))
4956
return tuple(sorted(models))
5057

51-
# Quick check helper
52-
@staticmethod
53-
def supports_model(name: str) -> bool:
54-
return name in _available
55-
56-
# Helper class (unchanged except for optional new method)
58+
# Helper class
5759
class Helper(ExperimentHelper):
5860
def get_helper_name_prefix(self):
5961
models = []
@@ -69,12 +71,31 @@ def get_helper_name_prefix(self):
6971
return models
7072
return "no_model"
7173

72-
# Optional: expose *available* (not selected) models via helper, too
73-
def get_available_models(self):
74-
models = set()
75-
for cls in type(self).__mro__:
76-
models.update(getattr(cls, "_available_programming_models", ()))
77-
return tuple(sorted(models))
74+
def get_spack_variants(self):
75+
models = []
76+
model_dict = {
77+
ProgrammingModelType.Openmp.value: ["+openmp", "~openmp"],
78+
ProgrammingModelType.Cuda.value: [
79+
"+cuda cuda_arch={cuda_arch}",
80+
"~cuda",
81+
],
82+
ProgrammingModelType.Rocm.value: [
83+
"+rocm amdgpu_target={rocm_arch}",
84+
"~rocm",
85+
],
86+
}
87+
for s in [
88+
ProgrammingModelType.Openmp.value,
89+
ProgrammingModelType.Cuda.value,
90+
ProgrammingModelType.Rocm.value,
91+
]:
92+
if is_available(s):
93+
if self.spec.satisfies("+" + s):
94+
models.append(model_dict[s][0])
95+
else:
96+
models.append(model_dict[s][1])
97+
98+
return " ".join(models)
7899

79100
return type(
80101
"ProgrammingModelType",

lib/benchpark/test/experiment_errors.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
def test_programming_model_checks():
1313
# babelstream mpi-only not valid
1414
with pytest.raises(
15-
BenchparkError, match=r"mpi.*are not valid programming models for.*babelstream"
15+
BenchparkError,
16+
match=r"babelstream.*cannot run with MPI only without inheriting from",
1617
):
1718
spec = benchpark.spec.ExperimentSpec("babelstream").concretize()
1819
experiment = spec.experiment # noqa: F841
1920

2021
# stream+openmp not valid
21-
with pytest.raises(
22-
Exception, match=r"openmp.*are not valid programming models for.*stream.*mpi"
23-
):
22+
with pytest.raises(Exception, match=r"openmp is not a valid variant of stream"):
2423
spec = benchpark.spec.ExperimentSpec(
2524
"stream+openmp workload=stream"
2625
).concretize()

0 commit comments

Comments
 (0)