Skip to content

Commit 78e7ce2

Browse files
author
Vasileios Karakasis
authored
Merge pull request #2140 from ekouts/bugfix/autodetect_modules
[bugfix] Use partition's and system's environment when autodetecting the topology
2 parents 5b17b95 + 5a3486b commit 78e7ce2

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

reframe/core/schedulers/slurm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ def filternodes(self, job, nodes):
292292
# Collect options that restrict node selection, but we need to first
293293
# create a mutable list out of the immutable SequenceView that
294294
# sched_access is
295-
options = list(job.sched_access + job.options + job.cli_options)
295+
options = job.sched_access + job.options + job.cli_options
296296
option_parser = ArgumentParser()
297297
option_parser.add_argument('--reservation')
298298
option_parser.add_argument('-p', '--partition')

reframe/frontend/autodetect.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import tempfile
1111

1212
import reframe as rfm
13+
import reframe.core.runtime as runtime
1314
import reframe.utility.osext as osext
1415
from reframe.core.exceptions import ConfigError
1516
from reframe.core.logging import getlogger
16-
from reframe.core.runtime import runtime
1717
from reframe.core.schedulers import Job
1818
from reframe.utility.cpuinfo import cpuinfo
1919

@@ -60,7 +60,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
6060
def _subschema(fragment):
6161
'''Create a configuration subschema.'''
6262

63-
full_schema = runtime().site_config.schema
63+
full_schema = runtime.runtime().site_config.schema
6464
return {
6565
'$schema': full_schema['$schema'],
6666
'defs': full_schema['defs'],
@@ -111,29 +111,28 @@ def _is_part_local(part):
111111

112112

113113
def _remote_detect(part):
114-
def _emit_script(job):
114+
def _emit_script(job, env):
115115
launcher_cmd = job.launcher.run_command(job)
116116
commands = [
117117
f'./bootstrap.sh',
118118
f'{launcher_cmd} ./bin/reframe --detect-host-topology=topo.json'
119119
]
120-
job.prepare(commands, trap_errors=True)
120+
job.prepare(commands, env, trap_errors=True)
121121

122122
getlogger().info(
123123
f'Detecting topology of remote partition {part.fullname!r}: '
124124
f'this may take some time...'
125-
126125
)
127126
topo_info = {}
128127
try:
129-
prefix = runtime().get_option('general/0/remote_workdir')
128+
prefix = runtime.runtime().get_option('general/0/remote_workdir')
130129
with _copy_reframe(prefix) as dirname:
131130
with osext.change_dir(dirname):
132131
job = Job.create(part.scheduler,
133132
part.launcher_type(),
134133
name='rfm-detect-job',
135134
sched_access=part.access)
136-
_emit_script(job)
135+
_emit_script(job, [part.local_env])
137136
getlogger().debug('submitting detection script')
138137
_log_contents(job.script_filename)
139138
job.submit()
@@ -149,7 +148,7 @@ def _emit_script(job):
149148

150149

151150
def detect_topology():
152-
rt = runtime()
151+
rt = runtime.runtime()
153152
detect_remote_systems = rt.get_option('general/0/remote_detect')
154153
topo_prefix = os.path.join(os.getenv('HOME'), '.reframe/topology')
155154
for part in rt.system.partitions:
@@ -213,12 +212,22 @@ def detect_topology():
213212
if not found_procinfo:
214213
# No topology found, try to auto-detect it
215214
getlogger().debug(f'> no topology file found; auto-detecting...')
215+
modules = list(rt.system.preload_environ.modules)
216+
vars = dict(rt.system.preload_environ.variables.items())
216217
if _is_part_local(part):
218+
modules += part.local_env.modules
219+
vars.update(part.local_env.variables)
220+
217221
# Unconditionally detect the system for fully local partitions
218-
part.processor._info = cpuinfo()
222+
with runtime.temp_environment(modules=modules, variables=vars):
223+
part.processor._info = cpuinfo()
224+
219225
_save_info(topo_file, part.processor.info)
220226
elif detect_remote_systems:
221-
part.processor._info = _remote_detect(part)
227+
with runtime.temp_environment(modules=temp_modules,
228+
variables=temp_vars):
229+
part.processor._info = _remote_detect(part)
230+
222231
if part.processor.info:
223232
_save_info(topo_file, part.processor.info)
224233

reframe/utility/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,12 @@ class SequenceView(collections.abc.Sequence):
13661366
:raises TypeError: If the container does not fulfill the
13671367
:py:class:`collections.abc.Sequence` interface.
13681368
1369+
.. note::
1370+
1371+
You can concatenate a :class:`SequenceView` with a container of the
1372+
same type as the underlying container of the view, in which case a new
1373+
container with the concatenated elements will be returned.
1374+
13691375
'''
13701376

13711377
def __init__(self, container):
@@ -1416,13 +1422,16 @@ def __reversed__(self):
14161422
return self.__container.__reversed__()
14171423

14181424
def __add__(self, other):
1419-
if not isinstance(other, collections.abc.Sequence):
1425+
if not isinstance(other, type(self.__container)):
14201426
return NotImplemented
14211427

1422-
return SequenceView(self.__container + other)
1428+
return self.__container + other
1429+
1430+
def __radd__(self, other):
1431+
if not isinstance(other, type(self.__container)):
1432+
return NotImplemented
14231433

1424-
def __iadd__(self, other):
1425-
return NotImplemented
1434+
return other + self.__container
14261435

14271436
def __eq__(self, other):
14281437
if isinstance(other, SequenceView):

unittests/test_utility.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,14 +1072,18 @@ def test_sequence_view():
10721072
# Assert immutability
10731073
m = l + [3, 4]
10741074
assert [1, 2, 2, 3, 4] == m
1075-
assert isinstance(m, util.SequenceView)
1075+
assert isinstance(m, list)
10761076

1077-
m = l
1078-
l += [3, 4]
1079-
assert m is not l
1080-
assert [1, 2, 2] == m
1081-
assert [1, 2, 2, 3, 4] == l
1082-
assert isinstance(l, util.SequenceView)
1077+
m_orig = m = util.SequenceView([1])
1078+
m += [3, 4]
1079+
assert m is not m_orig
1080+
assert [1] == m_orig
1081+
assert [1, 3, 4] == m
1082+
assert isinstance(m, list)
1083+
1084+
n = m + l
1085+
assert [1, 3, 4, 1, 2, 2] == n
1086+
assert isinstance(n, list)
10831087

10841088
with pytest.raises(TypeError):
10851089
l[1] = 3
@@ -1542,6 +1546,7 @@ def test_jsonext_dumps():
15421546
)
15431547
assert '{"(1, 2, 3)": 1}' == jsonext.dumps({(1, 2, 3): 1})
15441548

1549+
15451550
# Classes to test JSON deserialization
15461551

15471552
class _D(jsonext.JSONSerializable):

0 commit comments

Comments
 (0)