[oneapi] fix mkl deps, externally installed, and docs (#22607)

This commit is contained in:
Robert Cohn 2021-04-07 12:31:08 -04:00 committed by GitHub
parent 6c16f5c5d5
commit c8b4414230
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 55 deletions

View File

@ -38,21 +38,25 @@ Intel no longer releases new versions of Parallel Studio, which can be
used in Spack via the :ref:<intelpackage>. All of its components can
now be found in oneAPI.
Example
=======
Examples
========
We start with a simple example that will be sufficient for most
users. Install the oneAPI compilers::
Building a Package With icx
---------------------------
In this example, we build patchelf with ``icc`` and ``icx``. The
compilers are installed with spack.
Install the oneAPI compilers::
spack install intel-oneapi-compilers
Add the oneAPI compilers to the set of compilers that Spack can use::
Add the compilers to your ``compilers.yaml`` so spack can use them::
spack compiler add `spack location -i intel-oneapi-compilers`/compiler/latest/linux/bin/intel64
spack compiler add `spack location -i intel-oneapi-compilers`/compiler/latest/linux/bin
This adds the compilers to your ``compilers.yaml``. Verify that the
compilers are available::
Verify that the compilers are available::
spack compiler list
@ -72,9 +76,11 @@ To build with with ``icx``, do ::
spack install patchelf%oneapi
In addition to compilers, oneAPI contains many libraries. The ``hdf5``
package works with any compatible MPI implementation. To build
``hdf5`` with Intel oneAPI MPI do::
Using oneAPI MPI to Satisfy a Virtual Dependence
------------------------------------------------------
The ``hdf5`` package works with any compatible MPI implementation. To
build ``hdf5`` with Intel oneAPI MPI do::
spack install hdf5 +mpi ^intel-oneapi-mpi
@ -95,11 +101,23 @@ To use the compilers, add some information about the installation to
spack compiler add /opt/intel/oneapi/compiler/latest/linux/bin
Adapt the paths above if you did not install the tools in the default
location. After adding the compilers, using them in Spack will be
exactly the same as if you had installed the
``intel-oneapi-compilers`` package. Another option is to manually add
the configuration to ``compilers.yaml`` as described in :ref:`Compiler
configuration <compiler-config>`.
location. After adding the compilers, using them is the same
as if you had installed the ``intel-oneapi-compilers`` package.
Another option is to manually add the configuration to
``compilers.yaml`` as described in :ref:`Compiler configuration
<compiler-config>`.
Libraries
---------
If you want Spack to use MKL that you have installed without Spack in
the default location, then add the following to
``~/.spack/packages.yaml``, adjusting the version as appropriate::
intel-oneapi-mkl:
externals:
- spec: intel-oneapi-mkl@2021.1.1
prefix: /opt/intel/oneapi/
Using oneAPI Tools Installed by Spack

View File

@ -8,13 +8,13 @@
"""
from sys import platform
from os.path import basename, dirname, isdir, join
from os.path import basename, dirname, isdir
from spack.package import Package
from spack.util.environment import EnvironmentModifications
from spack.util.executable import Executable
from llnl.util.filesystem import find_headers, find_libraries
from llnl.util.filesystem import find_headers, find_libraries, join_path
class IntelOneApiPackage(Package):
@ -33,6 +33,11 @@ def component_dir(self):
"""Subdirectory for this component in the install prefix."""
raise NotImplementedError
@property
def component_path(self):
"""Path to component <prefix>/<component>/<version>."""
return join_path(self.prefix, self.component_dir, str(self.spec.version))
def install(self, spec, prefix, installer_path=None):
"""Shared install method for all oneapi packages."""
@ -53,21 +58,20 @@ def install(self, spec, prefix, installer_path=None):
'--install-dir', prefix)
# Some installers have a bug and do not return an error code when failing
if not isdir(join(prefix, self.component_dir)):
if not isdir(join_path(prefix, self.component_dir)):
raise RuntimeError('install failed')
def setup_run_environment(self, env):
"""Adds environment variables to the generated module file.
These environment variables come from running:
.. code-block:: console
$ source {prefix}/setvars.sh --force
$ source {prefix}/{component}/{version}/env/vars.sh
"""
env.extend(EnvironmentModifications.from_sourcing_file(
join(self.prefix, self.component_dir, 'latest/env/vars.sh')))
join_path(self.component_path, 'env', 'vars.sh')))
class IntelOneApiLibraryPackage(IntelOneApiPackage):
@ -75,12 +79,11 @@ class IntelOneApiLibraryPackage(IntelOneApiPackage):
@property
def headers(self):
include_path = '%s/%s/latest/include' % (
self.prefix, self.component_dir)
include_path = join_path(self.component_path, 'include')
return find_headers('*', include_path, recursive=True)
@property
def libs(self):
lib_path = '%s/%s/latest/lib/intel64' % (self.prefix, self.component_dir)
lib_path = join_path(self.component_path, 'lib', 'intel64')
lib_path = lib_path if isdir(lib_path) else dirname(lib_path)
return find_libraries('*', root=lib_path, shared=True, recursive=True)

View File

@ -4,8 +4,8 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import subprocess
from os import path
import subprocess
from sys import platform
from spack import *
@ -36,19 +36,16 @@ class IntelOneapiCompilers(IntelOneApiPackage):
def component_dir(self):
return 'compiler'
def _join_prefix(self, p):
return path.join(self.prefix, 'compiler', 'latest', 'linux', p)
def _ld_library_path(self):
dirs = ['lib',
path.join('lib', 'x64'),
path.join('lib', 'emu'),
path.join('lib', 'oclfpga', 'host', 'linux64', 'lib'),
path.join('lib', 'oclfpga', 'linux64', 'lib'),
path.join('compiler', 'lib', 'intel64_lin'),
path.join('compiler', 'lib')]
join_path('lib', 'x64'),
join_path('lib', 'emu'),
join_path('lib', 'oclfpga', 'host', 'linux64', 'lib'),
join_path('lib', 'oclfpga', 'linux64', 'lib'),
join_path('compiler', 'lib', 'intel64_lin'),
join_path('compiler', 'lib')]
for dir in dirs:
yield self._join_prefix(dir)
yield join_path(self.component_path, 'linux', dir)
def install(self, spec, prefix):
# install cpp
@ -60,22 +57,23 @@ def install(self, spec, prefix):
super(IntelOneapiCompilers, self).install(
spec,
prefix,
installer_path=glob.glob(path.join('fortran-installer', '*'))[0])
installer_path=glob.glob(join_path('fortran-installer', '*'))[0])
# Some installers have a bug and do not return an error code when failing
if not path.isfile(path.join(prefix, 'compiler', 'latest', 'linux',
if not path.isfile(join_path(self.component_path, 'linux',
'bin', 'intel64', 'ifort')):
raise RuntimeError('install failed')
# set rpath so 'spack compiler add' can check version strings
# without setting LD_LIBRARY_PATH
rpath = ':'.join(self._ld_library_path())
patch_dirs = [path.join('compiler', 'lib', 'intel64_lin'),
path.join('compiler', 'lib', 'intel64'),
patch_dirs = [join_path('compiler', 'lib', 'intel64_lin'),
join_path('compiler', 'lib', 'intel64'),
'bin']
for pd in patch_dirs:
patchables = glob.glob(self._join_prefix(path.join(pd, '*')))
patchables.append(self._join_prefix(path.join('lib', 'icx-lto.so')))
patchables = glob.glob(join_path(self.component_path, 'linux', pd, '*'))
patchables.append(join_path(self.component_path,
'linux', 'lib', 'icx-lto.so'))
for file in patchables:
# Try to patch all files, patchelf will do nothing if
# file should not be patched

View File

@ -36,6 +36,8 @@ def component_dir(self):
@property
def libs(self):
lib_path = '{0}/{1}/latest/lib/intel64'.format(self.prefix, self.component_dir)
mkl_libs = ['libmkl_intel_ilp64', 'libmkl_sequential', 'libmkl_core']
return find_libraries(mkl_libs, root=lib_path, shared=True, recursive=False)
lib_path = join_path(self.component_path, 'lib', 'intel64')
mkl_libs = ['libmkl_intel_lp64', 'libmkl_sequential', 'libmkl_core']
libs = find_libraries(mkl_libs, root=lib_path, shared=True, recursive=False)
libs += find_system_libraries(['libpthread', 'libm', 'libdl'], shared=True)
return libs

View File

@ -4,7 +4,6 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from os import path
import subprocess
from sys import platform
@ -34,7 +33,7 @@ def component_dir(self):
return 'mpi'
def setup_dependent_package(self, module, dep_spec):
dir = join_path(self.prefix, 'mpi', 'latest', 'bin')
dir = join_path(self.component_path, 'bin')
self.spec.mpicc = join_path(dir, 'mpicc')
self.spec.mpicxx = join_path(dir, 'mpicxx')
self.spec.mpif77 = join_path(dir, 'mpif77')
@ -48,7 +47,7 @@ def setup_dependent_build_environment(self, env, dependent_spec):
env.set('MPICH_FC', spack_fc)
# Set compiler wrappers for dependent build stage
dir = self._join_prefix('bin')
dir = join_path(self.component_path, 'bin')
env.set('MPICC', join_path(dir, 'mpicc'))
env.set('MPICXX', join_path(dir, 'mpicxx'))
env.set('MPIF77', join_path(dir, 'mpif77'))
@ -58,22 +57,19 @@ def setup_dependent_build_environment(self, env, dependent_spec):
@property
def libs(self):
libs = []
for dir in [path.join('lib', 'release_mt'),
for dir in [join_path('lib', 'release_mt'),
'lib',
path.join('libfabric', 'lib')]:
lib_path = path.join(self.prefix, 'mpi', 'latest', dir)
join_path('libfabric', 'lib')]:
lib_path = join_path(self.component_path, dir)
ldir = find_libraries('*', root=lib_path, shared=True, recursive=False)
libs += ldir
return libs
def _join_prefix(self, path):
return join_path(self.prefix, 'mpi', 'latest', path)
def install(self, spec, prefix):
super(IntelOneapiMpi, self).install(spec, prefix)
# need to patch libmpi.so so it can always find libfabric
libfabric_rpath = self._join_prefix(path.join('libfabric', 'lib'))
libfabric_rpath = join_path(self.component_path, 'libfabric', 'lib')
for lib_version in ['debug', 'release', 'release_mt', 'debug_mt']:
file = self._join_prefix(path.join('lib', lib_version, 'libmpi.so'))
file = join_path(self.component_path, 'lib', lib_version, 'libmpi.so')
subprocess.call(['patchelf', '--set-rpath', libfabric_rpath, file])