Skip to content

Commit 712f9d2

Browse files
Merge pull request #3665 from boegel/oneapi
add support for using oneAPI versions of 'intel' toolchain components
2 parents e977592 + 3c1e6d7 commit 712f9d2

File tree

5 files changed

+127
-45
lines changed

5 files changed

+127
-45
lines changed

easybuild/framework/easyconfig/easyconfig.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def cache_aware_func(toolchain, incl_capabilities=False):
220220
return cache_aware_func
221221

222222

223-
def det_subtoolchain_version(current_tc, subtoolchain_name, optional_toolchains, cands, incl_capabilities=False):
223+
def det_subtoolchain_version(current_tc, subtoolchain_names, optional_toolchains, cands, incl_capabilities=False):
224224
"""
225225
Returns unique version for subtoolchain, in tc dict.
226226
If there is no unique version:
@@ -229,30 +229,46 @@ def det_subtoolchain_version(current_tc, subtoolchain_name, optional_toolchains,
229229
optional toolchains or system toolchain without add_system_to_minimal_toolchains.
230230
* in all other cases, raises an exception.
231231
"""
232-
uniq_subtc_versions = set([subtc['version'] for subtc in cands if subtc['name'] == subtoolchain_name])
233232
# init with "skipped"
234233
subtoolchain_version = None
235234

236-
# system toolchain: bottom of the hierarchy
237-
if is_system_toolchain(subtoolchain_name):
238-
add_system_to_minimal_toolchains = build_option('add_system_to_minimal_toolchains')
239-
if not add_system_to_minimal_toolchains and build_option('add_dummy_to_minimal_toolchains'):
240-
depr_msg = "Use --add-system-to-minimal-toolchains instead of --add-dummy-to-minimal-toolchains"
241-
_log.deprecated(depr_msg, '5.0')
242-
add_system_to_minimal_toolchains = True
243-
244-
if add_system_to_minimal_toolchains and not incl_capabilities:
245-
subtoolchain_version = ''
246-
elif len(uniq_subtc_versions) == 1:
247-
subtoolchain_version = list(uniq_subtc_versions)[0]
248-
elif len(uniq_subtc_versions) == 0:
249-
if subtoolchain_name not in optional_toolchains:
235+
# ensure we always have a tuple of alternative subtoolchain names, which makes things easier below
236+
if isinstance(subtoolchain_names, string_type):
237+
subtoolchain_names = (subtoolchain_names,)
238+
239+
system_subtoolchain = False
240+
241+
for subtoolchain_name in subtoolchain_names:
242+
243+
uniq_subtc_versions = set([subtc['version'] for subtc in cands if subtc['name'] == subtoolchain_name])
244+
245+
# system toolchain: bottom of the hierarchy
246+
if is_system_toolchain(subtoolchain_name):
247+
add_system_to_minimal_toolchains = build_option('add_system_to_minimal_toolchains')
248+
if not add_system_to_minimal_toolchains and build_option('add_dummy_to_minimal_toolchains'):
249+
depr_msg = "Use --add-system-to-minimal-toolchains instead of --add-dummy-to-minimal-toolchains"
250+
_log.deprecated(depr_msg, '5.0')
251+
add_system_to_minimal_toolchains = True
252+
253+
system_subtoolchain = True
254+
255+
if add_system_to_minimal_toolchains and not incl_capabilities:
256+
subtoolchain_version = ''
257+
elif len(uniq_subtc_versions) == 1:
258+
subtoolchain_version = list(uniq_subtc_versions)[0]
259+
elif len(uniq_subtc_versions) > 1:
260+
raise EasyBuildError("Multiple versions of %s found in dependencies of toolchain %s: %s",
261+
subtoolchain_name, current_tc['name'], ', '.join(sorted(uniq_subtc_versions)))
262+
263+
if subtoolchain_version is not None:
264+
break
265+
266+
if not system_subtoolchain and subtoolchain_version is None:
267+
if not all(n in optional_toolchains for n in subtoolchain_names):
268+
subtoolchain_names = ' or '.join(subtoolchain_names)
250269
# raise error if the subtoolchain considered now is not optional
251270
raise EasyBuildError("No version found for subtoolchain %s in dependencies of %s",
252-
subtoolchain_name, current_tc['name'])
253-
else:
254-
raise EasyBuildError("Multiple versions of %s found in dependencies of toolchain %s: %s",
255-
subtoolchain_name, current_tc['name'], ', '.join(sorted(uniq_subtc_versions)))
271+
subtoolchain_names, current_tc['name'])
256272

257273
return subtoolchain_version
258274

@@ -356,11 +372,16 @@ def get_toolchain_hierarchy(parent_toolchain, incl_capabilities=False):
356372
cands.append({'name': dep, 'version': current_tc_version})
357373

358374
# only retain candidates that match subtoolchain names
359-
cands = [c for c in cands if c['name'] in subtoolchain_names]
375+
cands = [c for c in cands if any(c['name'] == x or c['name'] in x for x in subtoolchain_names)]
360376

361377
for subtoolchain_name in subtoolchain_names:
362378
subtoolchain_version = det_subtoolchain_version(current_tc, subtoolchain_name, optional_toolchains, cands,
363379
incl_capabilities=incl_capabilities)
380+
381+
# narrow down alternative subtoolchain names to a single one, based on the selected version
382+
if isinstance(subtoolchain_name, tuple):
383+
subtoolchain_name = [cand['name'] for cand in cands if cand['version'] == subtoolchain_version][0]
384+
364385
# add to hierarchy and move to next
365386
if subtoolchain_version is not None and subtoolchain_name not in visited:
366387
tc = {'name': subtoolchain_name, 'version': subtoolchain_version}

easybuild/toolchains/fft/intelfftw.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,16 @@ def _set_fftw_variables(self):
5757
bitsuff = '_lp64'
5858
if self.options.get('i8', None):
5959
bitsuff = '_ilp64'
60-
compsuff = '_intel'
61-
if get_software_root('icc') is None:
62-
if get_software_root('PGI'):
63-
compsuff = '_pgi'
64-
elif get_software_root('GCC'):
65-
compsuff = '_gnu'
66-
else:
67-
error_msg = "Not using Intel compilers, PGI nor GCC, don't know compiler suffix for FFTW libraries."
68-
raise EasyBuildError(error_msg)
60+
61+
if get_software_root('icc') or get_software_root('intel-compilers'):
62+
compsuff = '_intel'
63+
elif get_software_root('PGI'):
64+
compsuff = '_pgi'
65+
elif get_software_root('GCC'):
66+
compsuff = '_gnu'
67+
else:
68+
error_msg = "Not using Intel compilers, PGI nor GCC, don't know compiler suffix for FFTW libraries."
69+
raise EasyBuildError(error_msg)
6970

7071
interface_lib = "fftw3xc%s%s" % (compsuff, picsuff)
7172
fftw_libs = [interface_lib]

easybuild/toolchains/iimpi.py

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,80 @@
3232
import re
3333

3434
from easybuild.toolchains.iccifort import IccIfort
35+
from easybuild.toolchains.intel_compilers import IntelCompilersToolchain
3536
from easybuild.toolchains.mpi.intelmpi import IntelMPI
3637

3738

38-
class Iimpi(IccIfort, IntelMPI):
39+
class Iimpi(IccIfort, IntelCompilersToolchain, IntelMPI):
3940
"""
4041
Compiler toolchain with Intel compilers (icc/ifort), Intel MPI.
4142
"""
4243
NAME = 'iimpi'
43-
SUBTOOLCHAIN = IccIfort.NAME
44+
# compiler-only subtoolchain can't be determine statically
45+
# since depends on toolchain version (see below),
46+
# so register both here as possible alternatives (which is taken into account elsewhere)
47+
SUBTOOLCHAIN = [(IntelCompilersToolchain.NAME, IccIfort.NAME)]
48+
49+
def __init__(self, *args, **kwargs):
50+
"""Constructor for Iimpi toolchain class."""
51+
52+
super(Iimpi, self).__init__(*args, **kwargs)
53+
54+
# make sure a non-symbolic version (e.g., 'system') is used before making comparisons using LooseVersion
55+
if re.match('^[0-9]', self.version):
56+
# need to transform a version like '2016a' with something that is safe to compare with '8.0', '2016.01'
57+
# comparing subversions that include letters causes TypeErrors in Python 3
58+
# 'a' is assumed to be equivalent with '.01' (January), and 'b' with '.07' (June)
59+
# (good enough for this purpose)
60+
self.iimpi_ver = self.version.replace('a', '.01').replace('b', '.07')
61+
if LooseVersion(self.iimpi_ver) >= LooseVersion('2020.12'):
62+
self.oneapi_gen = True
63+
self.SUBTOOLCHAIN = IntelCompilersToolchain.NAME
64+
self.COMPILER_MODULE_NAME = IntelCompilersToolchain.COMPILER_MODULE_NAME
65+
else:
66+
self.oneapi_gen = False
67+
self.SUBTOOLCHAIN = IccIfort.NAME
68+
self.COMPILER_MODULE_NAME = IccIfort.COMPILER_MODULE_NAME
69+
else:
70+
self.iimpi_ver = self.version
71+
self.oneapi_gen = False
4472

4573
def is_deprecated(self):
4674
"""Return whether or not this toolchain is deprecated."""
47-
# need to transform a version like '2016a' with something that is safe to compare with '8.0', '2000', '2016.01'
48-
# comparing subversions that include letters causes TypeErrors in Python 3
49-
# 'a' is assumed to be equivalent with '.01' (January), and 'b' with '.07' (June) (good enough for this purpose)
50-
version = self.version.replace('a', '.01').replace('b', '.07')
5175

5276
deprecated = False
77+
5378
# make sure a non-symbolic version (e.g., 'system') is used before making comparisons using LooseVersion
54-
if re.match('^[0-9]', version):
55-
iimpi_ver = LooseVersion(version)
79+
if re.match('^[0-9]', str(self.iimpi_ver)):
80+
loosever = LooseVersion(self.iimpi_ver)
5681
# iimpi toolchains older than iimpi/2016.01 are deprecated
5782
# iimpi 8.1.5 is an exception, since it used in intel/2016a (which is not deprecated yet)
58-
if iimpi_ver < LooseVersion('8.0'):
83+
if loosever < LooseVersion('8.0'):
5984
deprecated = True
60-
elif iimpi_ver > LooseVersion('2000') and iimpi_ver < LooseVersion('2016.01'):
85+
elif loosever > LooseVersion('2000') and loosever < LooseVersion('2016.01'):
6186
deprecated = True
6287

6388
return deprecated
89+
90+
def is_dep_in_toolchain_module(self, *args, **kwargs):
91+
"""Check whether a specific software name is listed as a dependency in the module for this toolchain."""
92+
if self.oneapi_gen:
93+
res = IntelCompilersToolchain.is_dep_in_toolchain_module(self, *args, **kwargs)
94+
else:
95+
res = IccIfort.is_dep_in_toolchain_module(self, *args, **kwargs)
96+
97+
return res
98+
99+
def _set_compiler_vars(self):
100+
"""Intel compilers-specific adjustments after setting compiler variables."""
101+
if self.oneapi_gen:
102+
IntelCompilersToolchain._set_compiler_vars(self)
103+
else:
104+
IccIfort._set_compiler_vars(self)
105+
106+
def set_variables(self):
107+
"""Intel compilers-specific adjustments after setting compiler variables."""
108+
if self.oneapi_gen:
109+
IntelCompilersToolchain.set_variables(self)
110+
else:
111+
IccIfort.set_variables(self)

easybuild/toolchains/linalg/intelmkl.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
:author: Stijn De Weirdt (Ghent University)
2929
:author: Kenneth Hoste (Ghent University)
3030
"""
31+
import os
3132
from distutils.version import LooseVersion
3233

3334
from easybuild.toolchains.compiler.gcc import TC_CONSTANT_GCC
@@ -152,13 +153,18 @@ def _set_blas_variables(self):
152153
raise EasyBuildError("_set_blas_variables: 32-bit libraries not supported yet for IMKL v%s (> v10.3)",
153154
found_version)
154155
else:
155-
self.BLAS_LIB_DIR = ['mkl/lib/intel64']
156-
if ver >= LooseVersion('10.3.4') and ver < LooseVersion('11.1'):
157-
self.BLAS_LIB_DIR.append('compiler/lib/intel64')
156+
if ver >= LooseVersion('2021'):
157+
basedir = os.path.join('mkl', found_version)
158158
else:
159-
self.BLAS_LIB_DIR.append('lib/intel64')
159+
basedir = 'mkl'
160+
161+
self.BLAS_LIB_DIR = [os.path.join(basedir, 'lib', 'intel64')]
162+
if ver >= LooseVersion('10.3.4') and ver < LooseVersion('11.1'):
163+
self.BLAS_LIB_DIR.append(os.path.join('compiler', 'lib', 'intel64'))
164+
elif ver < LooseVersion('2021'):
165+
self.BLAS_LIB_DIR.append(os.path.join('lib', 'intel64'))
160166

161-
self.BLAS_INCLUDE_DIR = ['mkl/include']
167+
self.BLAS_INCLUDE_DIR = [os.path.join(basedir, 'include')]
162168

163169
super(IntelMKL, self)._set_blas_variables()
164170

test/framework/easyconfig.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3380,6 +3380,12 @@ def test_det_subtoolchain_version(self):
33803380
for subtoolchain_name in subtoolchains[current_tc['name']]]
33813381
self.assertEqual(versions, ['4.9.3', ''])
33823382

3383+
# test det_subtoolchain_version when two alternatives for subtoolchain are specified
3384+
current_tc = {'name': 'gompi', 'version': '2018b'}
3385+
cands = [{'name': 'GCC', 'version': '7.3.0-2.30'}]
3386+
subtc_version = det_subtoolchain_version(current_tc, ('GCCcore', 'GCC'), optional_toolchains, cands)
3387+
self.assertEqual(subtc_version, '7.3.0-2.30')
3388+
33833389
def test_verify_easyconfig_filename(self):
33843390
"""Test verify_easyconfig_filename function"""
33853391
test_ecs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')

0 commit comments

Comments
 (0)