Skip to content

Commit 78d0414

Browse files
author
Vasileios Karakasis
authored
Merge branch 'master' into tutorial/eb
2 parents 8fa5744 + 285d22f commit 78d0414

24 files changed

+964
-66
lines changed

ci-scripts/ci-runner.bash

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,7 @@ if [ "X${MODULEUSE}" != "X" ]; then
125125
module use ${MODULEUSE}
126126
fi
127127

128-
parallel_opts="--workers=auto --forked"
129-
if [[ $(hostname) =~ tsa|uan ]]; then
130-
parallel_opts=""
131-
fi
128+
parallel_opts=""
132129

133130
# Bootstrap ReFrame
134131
./bootstrap.sh

config/cscs.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@
717717
'cpeIntel'
718718
],
719719
'max_jobs': 100,
720+
'access': ['-Cmc', f'--account={osext.osgroup()}'],
720721
'resources': [
721722
{
722723
'name': 'switches',
@@ -753,7 +754,6 @@
753754
'PrgEnv-cray',
754755
'PrgEnv-gnu',
755756
'PrgEnv-intel',
756-
'PrgEnv-nvidia',
757757
'cpeAMD',
758758
'cpeCray',
759759
'cpeGNU',
@@ -781,7 +781,6 @@
781781
'PrgEnv-cray',
782782
'PrgEnv-gnu',
783783
'PrgEnv-intel',
784-
'PrgEnv-nvidia',
785784
'cpeAMD',
786785
'cpeCray',
787786
'cpeGNU',

docs/config_reference.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,13 @@ System Partition Configuration
341341
:default: ``{}``
342342

343343
Processor information for this partition stored in a `processor info object <#processor-info>`__.
344+
If not set, ReFrame will try to auto-detect this information (see :ref:`proc-autodetection` for more information).
344345

345346
.. versionadded:: 3.5.0
346347

348+
.. versionchanged:: 3.7.0
349+
ReFrame is now able to detect the processor information automatically.
350+
347351

348352
.. js:attribute:: .systems[].partitions[].devices
349353

@@ -1201,6 +1205,28 @@ General Configuration
12011205
The command-line option sets the configuration option to ``false``.
12021206

12031207

1208+
.. js:attribute:: .general[].remote_detect
1209+
1210+
:required: No
1211+
:default: ``false``
1212+
1213+
Try to auto-detect processor information of remote partitions as well.
1214+
This may slow down the initialization of the framework, since it involves submitting auto-detection jobs to the remote partitions.
1215+
For more information on how ReFrame auto-detects processor information, you may refer to :ref:`proc-autodetection`.
1216+
1217+
.. versionadded:: 3.7.0
1218+
1219+
1220+
.. js:attribute:: .general[].remote_workdir
1221+
1222+
:required: No
1223+
:default: ``"."``
1224+
1225+
The temporary directory prefix that will be used to create a fresh ReFrame clone, in order to auto-detect the processor information of a remote partition.
1226+
1227+
.. versionadded:: 3.7.0
1228+
1229+
12041230
.. js:attribute:: .general[].ignore_check_conflicts
12051231

12061232
:required: No

docs/configure.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,43 @@ Let's see some concrete examples:
397397
"CC"
398398
399399
If you explicitly query a configuration value which is not defined in the configuration file, ReFrame will print its default value.
400+
401+
402+
.. _proc-autodetection:
403+
404+
Auto-detecting processor information
405+
------------------------------------
406+
407+
.. versionadded:: 3.7.0
408+
409+
.. |devices| replace:: :attr:`devices`
410+
.. _devices: config_reference.html#.systems[].partitions[].devices
411+
.. |processor| replace:: :attr:`processor`
412+
.. _processor: config_reference.html#.systems[].partitions[].processor
413+
.. |detect_remote_system_topology| replace:: :attr:`detect_remote_system_topology`
414+
.. _detect_remote_system_topology: config_reference.html#.general[].detect_remote_system_topology
415+
416+
ReFrame is able to detect the processor topology of both local and remote partitions automatically.
417+
The processor and device information are made available to the tests through the corresponding attributes of the :attr:`~reframe.core.pipeline.RegressionTest.current_partition` allowing a test to modify its behavior accordingly.
418+
Currently, ReFrame supports auto-detection of the local or remote processor information only.
419+
It does not support auto-detection of devices, in which cases users should explicitly specify this information using the |devices|_ configuration option.
420+
The processor information auto-detection works as follows:
421+
422+
#. If the |processor|_ configuration is option is defined, then no auto-detection is attempted.
423+
424+
#. If the |processor|_ configuration option is not defined, ReFrame will look for a processor configuration metadata file in ``{configdir}/_meta/{system}-{part}/processor.json`` or in ``~/.reframe/topology/{system}-{part}/processor.json`` in case of the builtin configuration file.
425+
If the file is found, the topology information is loaded from there.
426+
These files are generated automatically by ReFrame from previous runs.
427+
428+
#. If the corresponding metadata files are not found, the processor information will be auto-detected.
429+
If the system partition is local (i.e., ``local`` scheduler + ``local`` launcher), the processor information is auto-detected unconditionally and stored in the corresponding metadata file for this partition.
430+
If the partition is remote, ReFrame will not try to auto-detect it unless the :envvar:`RFM_REMOTE_DETECT` or the |detect_remote_system_topology|_ configuration option is set.
431+
In that case, the steps to auto-detect the remote processor information are the following:
432+
433+
a. ReFrame creates a fresh clone of itself in a temporary directory created under ``.`` by default.
434+
This temporary directory prefix can be changed by setting the :envvar:`RFM_REMOTE_WORKDIR` environment variable.
435+
b. ReFrame changes to that directory and launches a job that will first bootstrap the fresh clone and then run that clone with ``{launcher} ./bin/reframe --detect-host-topology=topo.json``.
436+
The :option:`--detect-host-topology` option causes ReFrame to detect the topology of the current host,
437+
which in this case would be the remote compute nodes.
438+
439+
In case of errors during auto-detection, ReFrame will simply issue a warning and continue.

docs/manpage.rst

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,16 @@ Miscellaneous options
576576

577577
This option can also be set using the :envvar:`RFM_SYSTEM` environment variable.
578578

579+
.. _--detect-host-topology:
580+
581+
.. option:: --detect-host-topology[=FILE]
582+
583+
Detect the local host processor topology, store it to ``FILE`` and exit.
584+
If no ``FILE`` is specified, the standard output will be used.
585+
586+
.. versionadded:: 3.7.0
587+
588+
579589
.. option:: --failure-stats
580590

581591
Print failure statistics at the end of the run.
@@ -698,6 +708,36 @@ Here is an alphabetical list of the environment variables recognized by ReFrame:
698708
================================== ==================
699709

700710

711+
.. envvar:: RFM_REMOTE_DETECT
712+
713+
Auto-detect processor information of remote partitions as well.
714+
715+
.. table::
716+
:align: left
717+
718+
================================== ==================
719+
Associated command line option N/A
720+
Associated configuration parameter :js:attr:`remote_detect` general configuration parameter
721+
================================== ==================
722+
723+
.. versionadded:: 3.7.0
724+
725+
726+
.. envvar:: RFM_REMOTE_WORKDIR
727+
728+
The temporary directory prefix that will be used to create a fresh ReFrame clone, in order to auto-detect the processor information of a remote partition.
729+
730+
.. table::
731+
:align: left
732+
733+
================================== ==================
734+
Associated command line option N/A
735+
Associated configuration parameter :js:attr:`remote_workdir` general configuration parameter
736+
================================== ==================
737+
738+
.. versionadded:: 3.7.0
739+
740+
701741
.. envvar:: RFM_GRAYLOG_ADDRESS
702742

703743
The address of the Graylog server to send performance logs.
@@ -920,7 +960,7 @@ Here is an alphabetical list of the environment variables recognized by ReFrame:
920960
:align: left
921961

922962
================================== ==================
923-
Associated command line option n/a
963+
Associated command line option N/A
924964
Associated configuration parameter :js:attr:`resolve_module_conflicts` general configuration parameter
925965
================================== ==================
926966

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
archspec==0.1.2
12
docutils==0.16 # https://github.com/sphinx-doc/sphinx/issues/9001
23
jsonschema==3.2.0
34
semver==2.13.0

reframe/core/config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ def __getitem__(self, key):
101101
def __getattr__(self, attr):
102102
return getattr(self._pick_config(), attr)
103103

104+
@property
105+
def schema(self):
106+
'''Configuration schema'''
107+
return self._schema
108+
104109
def add_sticky_option(self, option, value):
105110
self._sticky_options[option] = value
106111

reframe/core/decorators.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ def _validate_test(cls):
9191
raise ValueError(f'decorated test ({cls.__qualname__!r}) has one or '
9292
f'more undefined parameters')
9393

94+
conditions = [VersionValidator(v) for v in cls._rfm_required_version]
95+
if (cls._rfm_required_version and
96+
not any(c.validate(osext.reframe_version()) for c in conditions)):
97+
98+
getlogger().warning(f"skipping incompatible test "
99+
f"'{cls.__qualname__}': not valid for ReFrame "
100+
f"version {osext.reframe_version().split('-')[0]}")
101+
return False
102+
103+
return True
104+
94105

95106
def simple_test(cls):
96107
'''Class decorator for registering tests with ReFrame.
@@ -101,10 +112,9 @@ def simple_test(cls):
101112
102113
.. versionadded:: 2.13
103114
'''
104-
_validate_test(cls)
105-
106-
for _ in cls.param_space:
107-
_register_test(cls)
115+
if _validate_test(cls):
116+
for _ in cls.param_space:
117+
_register_test(cls)
108118

109119
return cls
110120

@@ -139,14 +149,14 @@ def parameterized_test(*inst):
139149
)
140150

141151
def _do_register(cls):
142-
_validate_test(cls)
143-
if not cls.param_space.is_empty():
144-
raise ValueError(
145-
f'{cls.__qualname__!r} is already a parameterized test'
146-
)
152+
if _validate_test(cls):
153+
if not cls.param_space.is_empty():
154+
raise ValueError(
155+
f'{cls.__qualname__!r} is already a parameterized test'
156+
)
147157

148-
for args in inst:
149-
_register_test(cls, args)
158+
for args in inst:
159+
_register_test(cls, args)
150160

151161
return cls
152162

@@ -187,6 +197,12 @@ def required_version(*versions):
187197
These should be written as ``3.5.0`` and ``3.5.0-dev.0``.
188198
189199
'''
200+
warn.user_deprecation_warning(
201+
"the '@required_version' decorator is deprecated; please set "
202+
"the 'require_version' parameter in the class definition instead",
203+
from_version='3.7.0'
204+
)
205+
190206
if not versions:
191207
raise ValueError('no versions specified')
192208

@@ -198,8 +214,10 @@ def _skip_tests(cls):
198214
mod.__rfm_skip_tests = set()
199215

200216
if not any(c.validate(osext.reframe_version()) for c in conditions):
201-
getlogger().info('skipping incompatible test defined'
202-
' in class: %s' % cls.__name__)
217+
getlogger().warning(
218+
f"skipping incompatible test '{cls.__qualname__}': not valid "
219+
f"for ReFrame version {osext.reframe_version().split('-')[0]}"
220+
)
203221
mod.__rfm_skip_tests.add(cls)
204222

205223
return cls

reframe/core/meta.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def __prepare__(metacls, name, bases, **kwargs):
176176
namespace['variable'] = variables.TestVar
177177
namespace['required'] = variables.Undefined
178178

179+
# Utility decorators
179180
def bind(fn, name=None):
180181
'''Directive to bind a free function to a class.
181182
@@ -186,7 +187,14 @@ def bind(fn, name=None):
186187
namespace[inst.__name__] = inst
187188
return inst
188189

190+
def final(fn):
191+
'''Indicate that a function is final and cannot be overridden.'''
192+
193+
fn._rfm_final = True
194+
return fn
195+
189196
namespace['bind'] = bind
197+
namespace['final'] = final
190198

191199
# Hook-related functionality
192200
def run_before(stage):
@@ -205,8 +213,6 @@ def run_before(stage):
205213

206214
return hooks.attach_to('pre_' + stage)
207215

208-
namespace['run_before'] = run_before
209-
210216
def run_after(stage):
211217
'''Decorator for attaching a test method to a pipeline stage.
212218
@@ -228,6 +234,7 @@ def run_after(stage):
228234

229235
return hooks.attach_to('post_' + stage)
230236

237+
namespace['run_before'] = run_before
231238
namespace['run_after'] = run_after
232239
namespace['require_deps'] = hooks.require_deps
233240

@@ -259,7 +266,8 @@ class was created or even at the instance level (e.g. doing
259266

260267
directives = [
261268
'parameter', 'variable', 'bind', 'run_before', 'run_after',
262-
'require_deps', 'required', 'deferrable', 'sanity_function'
269+
'require_deps', 'required', 'deferrable', 'sanity_function',
270+
'final'
263271
]
264272
for b in directives:
265273
namespace.pop(b, None)
@@ -326,13 +334,12 @@ def __init__(cls, name, bases, namespace, **kwargs):
326334
if hasattr(v, '_rfm_final')}
327335

328336
# Add the final functions from its parents
329-
cls._final_methods.update(*(b._final_methods for b in bases
330-
if hasattr(b, '_final_methods')))
337+
bases_w_final = [b for b in bases if hasattr(b, '_final_methods')]
338+
cls._final_methods.update(*(b._final_methods for b in bases_w_final))
331339

332-
if getattr(cls, '_rfm_special_test', None):
340+
if getattr(cls, '_rfm_override_final', None):
333341
return
334342

335-
bases_w_final = [b for b in bases if hasattr(b, '_final_methods')]
336343
for v in namespace.values():
337344
for b in bases_w_final:
338345
if callable(v) and v.__name__ in b._final_methods:

0 commit comments

Comments
 (0)