From 95a95841ac3481c18688bffdf986f16b1c93b6ca Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Sun, 2 Mar 2025 21:52:01 +0100 Subject: [PATCH 1/7] simplify executable_opts with user_executable_opts --- eessi/testsuite/eessi_mixin.py | 8 +++ .../testsuite/tests/apps/espresso/espresso.py | 8 --- eessi/testsuite/tests/apps/gromacs.py | 16 +---- eessi/testsuite/tests/apps/lammps/lammps.py | 62 ++++++++----------- .../tests/apps/tensorflow/tensorflow.py | 14 ++--- 5 files changed, 41 insertions(+), 67 deletions(-) diff --git a/eessi/testsuite/eessi_mixin.py b/eessi/testsuite/eessi_mixin.py index 584f7f1d..187783fb 100644 --- a/eessi/testsuite/eessi_mixin.py +++ b/eessi/testsuite/eessi_mixin.py @@ -41,6 +41,7 @@ class EESSI_Mixin(RegressionMixin): # Set defaults for these class variables, can be overwritten by child class if desired measure_memory_usage = variable(bool, value=False) exact_memory = variable(bool, value=False) + user_executable_opts = variable(str, value='') scale = parameter(SCALES.keys()) bench_name = None bench_name_ci = None @@ -202,6 +203,13 @@ def log_runtime_info(self): get_full_modpath = f'echo "FULL_MODULEPATH: $(module --location show {self.module_name})"' self.postrun_cmds.append(get_full_modpath) + @run_before('run', always_last=True) + def mixin_set_user_executable_opts(self): + "Override executable_opts with user_executable_opts if set on the cmd line" + if self.user_executable_opts: + self.executable_opts = [self.user_executable_opts] + log(f'executable_opts set to {self.executable_opts}') + @run_after('run') def extract_runtime_info_from_log(self): """Extracts the printed runtime info from the job log and logs it as reframe variables""" diff --git a/eessi/testsuite/tests/apps/espresso/espresso.py b/eessi/testsuite/tests/apps/espresso/espresso.py index f19c8b7c..d39ff3f3 100644 --- a/eessi/testsuite/tests/apps/espresso/espresso.py +++ b/eessi/testsuite/tests/apps/espresso/espresso.py @@ -127,8 +127,6 @@ def set_tag_ci(self): @run_after('init') def set_executable_opts(self): """Set executable opts based on device_type parameter""" - num_default = 0 # If this test already has executable opts, they must have come from the command line - hooks.check_custom_executable_opts(self, num_default=num_default) # By default we run weak scaling since the strong scaling sizes need to change based on max node size and a # corresponding min node size has to be chozen. self.executable_opts += ['--size', str(self.default_weak_scaling_system_size), '--weak-scaling'] @@ -175,12 +173,6 @@ def set_tag_ci(self): self.tags.add('particles_lj') - @run_after('init') - def set_executable_opts(self): - """Allow executable opts to be overwritten from command line""" - num_default = 0 # If this test already has executable opts, they must have come from the command line - hooks.check_custom_executable_opts(self, num_default=num_default) - @run_after('setup') def set_mem(self): """ Setting an extra job option of memory. Here the assumption made is that HPC systems will contain at diff --git a/eessi/testsuite/tests/apps/gromacs.py b/eessi/testsuite/tests/apps/gromacs.py index 5617651b..721314c2 100644 --- a/eessi/testsuite/tests/apps/gromacs.py +++ b/eessi/testsuite/tests/apps/gromacs.py @@ -34,7 +34,6 @@ from hpctestlib.sciapps.gromacs.benchmarks import gromacs_check -from eessi.testsuite import hooks from eessi.testsuite.constants import COMPUTE_UNIT, DEVICE_TYPES, SCALES from eessi.testsuite.eessi_mixin import EESSI_Mixin from eessi.testsuite.utils import find_modules, log @@ -54,6 +53,8 @@ class EESSI_GROMACS(EESSI_GROMACS_base, EESSI_Mixin): bench_name_ci = 'HECBioSim/Crambin' # input files are downloaded readonly_files = [''] + # executable_opts in addition to those set by the hpctestlib + executable_opts = ['-dlb', 'yes', '-npme', '-1'] def required_mem_per_node(self): return self.num_tasks_per_node * 1024 @@ -76,19 +77,6 @@ def set_compute_unit(self): msg = f"No mapping of device type {self.device_type} to a COMPUTE_UNIT was specified in this test" raise NotImplementedError(msg) - @run_after('setup') - def set_executable_opts(self): - """ - Add extra executable_opts, unless specified via --setvar executable_opts= - Set default executable_opts and support setting custom executable_opts on the cmd line. - """ - - num_default = 4 # normalized number of executable opts added by parent class (gromacs_check) - hooks.check_custom_executable_opts(self, num_default=num_default) - if not self.has_custom_executable_opts: - self.executable_opts += ['-dlb', 'yes', '-npme', '-1'] - log(f'executable_opts set to {self.executable_opts}') - @run_after('setup') def set_omp_num_threads(self): """ diff --git a/eessi/testsuite/tests/apps/lammps/lammps.py b/eessi/testsuite/tests/apps/lammps/lammps.py index e4c4044a..5e3a85d8 100644 --- a/eessi/testsuite/tests/apps/lammps/lammps.py +++ b/eessi/testsuite/tests/apps/lammps/lammps.py @@ -103,24 +103,19 @@ def assert_sanity(self): @run_after('setup') def set_executable_opts(self): """Set executable opts based on device_type parameter""" - num_default = 0 # If this test already has executable opts, they must have come from the command line - hooks.check_custom_executable_opts(self, num_default=num_default) - if not self.has_custom_executable_opts: - # should also check if the lammps is installed with kokkos. - # Because this exutable opt is only for that case. - if self.device_type == "gpu": - if 'kokkos' in self.module_name: - self.executable_opts += [ - f'-kokkos on t {self.num_cpus_per_task} g {self.num_gpus_per_node}', - '-suffix kk', - '-package kokkos newton on neigh half', - ] - utils.log(f'executable_opts set to {self.executable_opts}') - else: - self.executable_opts += [ - f'-suffix gpu -package gpu {self.num_gpus_per_node}', - ] - utils.log(f'executable_opts set to {self.executable_opts}') + # should also check if the lammps is installed with kokkos. + # Because this executable opt is only for that case. + if self.device_type == "gpu": + if 'kokkos' in self.module_name: + self.executable_opts += [ + f'-kokkos on t {self.num_cpus_per_task} g {self.num_gpus_per_node}', + '-suffix kk', + '-package kokkos newton on neigh half', + ] + utils.log(f'executable_opts set to {self.executable_opts}') + else: + self.executable_opts += [f'-suffix gpu -package gpu {self.num_gpus_per_node}'] + utils.log(f'executable_opts set to {self.executable_opts}') @rfm.simple_test @@ -163,21 +158,16 @@ def assert_sanity(self): @run_after('setup') def set_executable_opts(self): """Set executable opts based on device_type parameter""" - num_default = 0 # If this test already has executable opts, they must have come from the command line - hooks.check_custom_executable_opts(self, num_default=num_default) - if not self.has_custom_executable_opts: - # should also check if the lammps is installed with kokkos. - # Because this exutable opt is only for that case. - if self.device_type == "gpu": - if 'kokkos' in self.module_name: - self.executable_opts += [ - f'-kokkos on t {self.num_cpus_per_task} g {self.num_gpus_per_node}', - '-suffix kk', - '-package kokkos newton on neigh half', - ] - utils.log(f'executable_opts set to {self.executable_opts}') - else: - self.executable_opts += [ - f'-suffix gpu -package gpu {self.num_gpus_per_node}', - ] - utils.log(f'executable_opts set to {self.executable_opts}') + # should also check if the lammps is installed with kokkos. + # Because this executable opt is only for that case. + if self.device_type == "gpu": + if 'kokkos' in self.module_name: + self.executable_opts += [ + f'-kokkos on t {self.num_cpus_per_task} g {self.num_gpus_per_node}', + '-suffix kk', + '-package kokkos newton on neigh half', + ] + utils.log(f'executable_opts set to {self.executable_opts}') + else: + self.executable_opts += [f'-suffix gpu -package gpu {self.num_gpus_per_node}'] + utils.log(f'executable_opts set to {self.executable_opts}') diff --git a/eessi/testsuite/tests/apps/tensorflow/tensorflow.py b/eessi/testsuite/tests/apps/tensorflow/tensorflow.py index b5b3e72b..b04af259 100644 --- a/eessi/testsuite/tests/apps/tensorflow/tensorflow.py +++ b/eessi/testsuite/tests/apps/tensorflow/tensorflow.py @@ -72,11 +72,8 @@ def perf(self): @run_after('init') def set_executable_opts(self): """Set executable opts based on device_type parameter""" - num_default = 0 # If this test already has executable opts, they must have come from the command line - hooks.check_custom_executable_opts(self, num_default=num_default) - if not self.has_custom_executable_opts: - self.executable_opts += ['--device', self.device_type] - utils.log(f'executable_opts set to {self.executable_opts}') + self.executable_opts += ['--device', self.device_type] + utils.log(f'executable_opts set to {self.executable_opts}') @run_after('init') def set_test_descr(self): @@ -97,7 +94,6 @@ def set_compute_unit(self): @run_after('setup') def set_thread_count_args(self): """Set executable opts defining the thread count""" - if not self.has_custom_executable_opts: - self.executable_opts += ['--intra-op-parallelism', '%s' % self.num_cpus_per_task] - self.executable_opts += ['--inter-op-parallelism', '1'] - utils.log(f'executable_opts set to {self.executable_opts}') + self.executable_opts += ['--intra-op-parallelism', '%s' % self.num_cpus_per_task] + self.executable_opts += ['--inter-op-parallelism', '1'] + utils.log(f'executable_opts set to {self.executable_opts}') From e2adaf141cd54531cb5246ed42206f8785f82810 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Mon, 3 Mar 2025 09:25:44 +0100 Subject: [PATCH 2/7] remove unused imports --- eessi/testsuite/tests/apps/lammps/lammps.py | 2 +- eessi/testsuite/tests/apps/tensorflow/tensorflow.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eessi/testsuite/tests/apps/lammps/lammps.py b/eessi/testsuite/tests/apps/lammps/lammps.py index 5e3a85d8..afa1f644 100644 --- a/eessi/testsuite/tests/apps/lammps/lammps.py +++ b/eessi/testsuite/tests/apps/lammps/lammps.py @@ -6,7 +6,7 @@ import reframe as rfm import reframe.utility.sanity as sn -from eessi.testsuite import hooks, utils +from eessi.testsuite import utils from eessi.testsuite.constants import * # noqa from eessi.testsuite.eessi_mixin import EESSI_Mixin diff --git a/eessi/testsuite/tests/apps/tensorflow/tensorflow.py b/eessi/testsuite/tests/apps/tensorflow/tensorflow.py index b04af259..5d2cc03e 100644 --- a/eessi/testsuite/tests/apps/tensorflow/tensorflow.py +++ b/eessi/testsuite/tests/apps/tensorflow/tensorflow.py @@ -8,7 +8,7 @@ from reframe.core.builtins import deferrable, parameter, run_after, sanity_function, performance_function import reframe.utility.sanity as sn -from eessi.testsuite import hooks, utils +from eessi.testsuite import utils from eessi.testsuite.constants import COMPUTE_UNIT, CPU, CPU_SOCKET, DEVICE_TYPES, GPU from eessi.testsuite.eessi_mixin import EESSI_Mixin From 60a195270cd0e173c067ddda84f9c8bd03850ac4 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 4 Mar 2025 22:29:01 +0100 Subject: [PATCH 3/7] improve logging --- eessi/testsuite/eessi_mixin.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/eessi/testsuite/eessi_mixin.py b/eessi/testsuite/eessi_mixin.py index 187783fb..e338ace8 100644 --- a/eessi/testsuite/eessi_mixin.py +++ b/eessi/testsuite/eessi_mixin.py @@ -204,11 +204,13 @@ def log_runtime_info(self): self.postrun_cmds.append(get_full_modpath) @run_before('run', always_last=True) - def mixin_set_user_executable_opts(self): + def EESSI_mixin_set_user_executable_opts(self): "Override executable_opts with user_executable_opts if set on the cmd line" if self.user_executable_opts: + log(f'Overwriting executable_opts {self.executable_opts} by executable_opts ' + 'specified on cmd line {[self.user_executable_opts]}') self.executable_opts = [self.user_executable_opts] - log(f'executable_opts set to {self.executable_opts}') + @run_after('run') def extract_runtime_info_from_log(self): From 1b5c7fe2eaa51788a11dc627ff77cdf9914618ac Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 4 Mar 2025 23:27:16 +0100 Subject: [PATCH 4/7] further simplify gromacs test --- eessi/testsuite/tests/apps/gromacs.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/eessi/testsuite/tests/apps/gromacs.py b/eessi/testsuite/tests/apps/gromacs.py index 721314c2..6d9f1570 100644 --- a/eessi/testsuite/tests/apps/gromacs.py +++ b/eessi/testsuite/tests/apps/gromacs.py @@ -85,13 +85,9 @@ def set_omp_num_threads(self): Set default number of OpenMP threads equal to number of CPUs per task. Also support setting OpenMP threads on the cmd line via custom executable option '-ntomp'. """ - - if '-ntomp' in self.executable_opts: - omp_num_threads = self.executable_opts[self.executable_opts.index('-ntomp') + 1] - else: - omp_num_threads = self.num_cpus_per_task - self.executable_opts += ['-ntomp', str(omp_num_threads)] - log(f'executable_opts set to {self.executable_opts}') + omp_num_threads = self.num_cpus_per_task + self.executable_opts += ['-ntomp', str(omp_num_threads)] + log(f'executable_opts set to {self.executable_opts}') self.env_vars['OMP_NUM_THREADS'] = omp_num_threads log(f'env_vars set to {self.env_vars}') From 68fcfa50e0684a31ccc4679fda6d61eb81b6fc87 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 4 Mar 2025 23:28:32 +0100 Subject: [PATCH 5/7] remove check_custom_executable_opts hook --- eessi/testsuite/hooks.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/eessi/testsuite/hooks.py b/eessi/testsuite/hooks.py index 0f746614..42d60287 100644 --- a/eessi/testsuite/hooks.py +++ b/eessi/testsuite/hooks.py @@ -619,18 +619,6 @@ def set_tag_scale(test: rfm.RegressionTest): log(f'tags set to {test.tags}') -def check_custom_executable_opts(test: rfm.RegressionTest, num_default: int = 0): - """" - Check if custom executable options were added with --setvar executable_opts=. - """ - # normalize options - test.executable_opts = shlex.split(' '.join(test.executable_opts)) - test.has_custom_executable_opts = False - if len(test.executable_opts) > num_default: - test.has_custom_executable_opts = True - log(f'has_custom_executable_opts set to {test.has_custom_executable_opts}') - - def set_compact_process_binding(test: rfm.RegressionTest): """ This hook sets a binding policy for process binding. From 26609baf56c903a62edc44c6dd868abdde50ca99 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 4 Mar 2025 23:30:53 +0100 Subject: [PATCH 6/7] remove unused import --- eessi/testsuite/hooks.py | 1 - 1 file changed, 1 deletion(-) diff --git a/eessi/testsuite/hooks.py b/eessi/testsuite/hooks.py index 42d60287..6ce5b58f 100644 --- a/eessi/testsuite/hooks.py +++ b/eessi/testsuite/hooks.py @@ -2,7 +2,6 @@ Hooks for adding tags, filtering and setting job resources in ReFrame tests """ import math -import shlex import reframe as rfm import reframe.core.logging as rflog From d9fab2bcfe18a091640f7d67d2ccc65eb6d58c48 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 4 Mar 2025 23:32:18 +0100 Subject: [PATCH 7/7] remove blank line --- eessi/testsuite/eessi_mixin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/eessi/testsuite/eessi_mixin.py b/eessi/testsuite/eessi_mixin.py index e338ace8..b954ef0d 100644 --- a/eessi/testsuite/eessi_mixin.py +++ b/eessi/testsuite/eessi_mixin.py @@ -211,7 +211,6 @@ def EESSI_mixin_set_user_executable_opts(self): 'specified on cmd line {[self.user_executable_opts]}') self.executable_opts = [self.user_executable_opts] - @run_after('run') def extract_runtime_info_from_log(self): """Extracts the printed runtime info from the job log and logs it as reframe variables"""