Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions easybuild/easyblocks/f/flexiblas.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,16 @@
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.environment import setvar
from easybuild.tools.filetools import write_file
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext

IMKL_CONF_TEMPLATE = """[IMKL]
library = libflexiblas_imkl_%(parallel)s_thread.so
[IMKL_SEQ]
library = libflexiblas_imkl_sequential.so
"""


class EB_FlexiBLAS(CMakeMake):
"""Support for building/installing FlexiBLAS."""
Expand All @@ -51,7 +58,8 @@ def extra_options():
'flexiblas_default': [None, "Default BLAS lib to set at compile time. If not defined, " +
"the first BLAS lib in backends or the list of dependencies is set as default",
CUSTOM],
'backends': [None, "List of (build)dependency names to use as BLAS library backends. " +
'backends': [None, "List of (build)dependency names to use as BLAS library backends, or " +
"'imkl', which does not need to be a (build)dependency." +
"If not defined, use the list of dependencies.", CUSTOM],
})
extra_vars['separate_build_dir'][0] = True
Expand All @@ -63,8 +71,10 @@ def __init__(self, *args, **kwargs):

dep_names = [dep['name'] for dep in self.cfg.dependencies()]
if self.cfg['backends']:
self.blas_libs = self.cfg['backends']
# make sure that all listed backends are (build)dependencies
self.blas_libs = self.cfg['backends'][:]
# make sure that all listed backends except imkl are (build)dependencies
if 'imkl' in self.blas_libs and 'imkl' not in dep_names:
self.blas_libs.remove('imkl')
backends_nodep = [x for x in self.blas_libs if x not in dep_names]
if backends_nodep:
raise EasyBuildError("One or more backends not listed as (build)dependencies: %s",
Expand Down Expand Up @@ -137,6 +147,18 @@ def configure_step(self):

super(EB_FlexiBLAS, self).configure_step(builddir=self.obj_builddir)

def install_step(self):
"""Install imkl configuration, found via FLEXIBLAS_LIBRARY_PATH set by imkl module."""

super(EB_FlexiBLAS, self).install_step()
if self.cfg['backends'] and 'imkl' in self.cfg['backends'] and 'imkl' not in self.blas_libs:
if self.toolchain.comp_family() == toolchain.GCC:
parallel = "gnu"
else:
parallel = "intel"
write_file(os.path.join(self.installdir, 'etc', 'flexiblasrc.d', 'imkl.conf'),
IMKL_CONF_TEMPLATE % {'parallel': parallel})

def test_step(self):
"""Run tests using each of the backends."""

Expand Down
49 changes: 49 additions & 0 deletions easybuild/easyblocks/i/imkl.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import glob
import itertools
import os
import shutil
import tempfile
from distutils.version import LooseVersion

Expand All @@ -63,6 +64,8 @@ def extra_options():
"""Add easyconfig parameters custom to imkl (e.g. interfaces)."""
extra_vars = {
'interfaces': [True, "Indicates whether interfaces should be built", CUSTOM],
'flexiblas': [None, "Indicates whether FlexiBLAS-compatible libraries should be built, "
"default from version 2021", CUSTOM],
}
return IntelBase.extra_options(extra_vars)

Expand All @@ -77,8 +80,12 @@ def __init__(self, *args, **kwargs):

if LooseVersion(self.version) >= LooseVersion('2021'):
self.mkl_basedir = os.path.join('mkl', self.version)
if self.cfg['flexiblas'] is None:
self.cfg['flexiblas'] = True
else:
self.mkl_basedir = 'mkl'
if self.cfg['flexiblas'] is None:
self.cfg['flexiblas'] = False

def prepare_step(self, *args, **kwargs):
"""Prepare build environment."""
Expand Down Expand Up @@ -285,6 +292,38 @@ def build_mkl_fftw_interfaces(self, libdir):

remove_dir(tmpbuild)

def build_mkl_flexiblas(self, flexiblasdir):
"""
Build libflexiblas_imkl_gnu_thread.so, libflexiblas_imkl_intel_thread.so,
and libflexiblas_imkl_sequential.so. They can be used as FlexiBLAS backends
via FLEXIBLAS_LIBRARY_PATH.
"""
builderdir = os.path.join(self.installdir, self.mkl_basedir, 'tools', 'builder')
change_dir(builderdir)
mkdir(flexiblasdir, parents=True)

# concatenate lists of all BLAS, CBLAS and LAPACK functions
with tempfile.NamedTemporaryFile(dir=self.builddir, mode="wt", delete=False) as dst:
listfilename = dst.name
self.log.debug("Created temporary file %s" % listfilename)
for lst in 'blas', 'cblas', 'lapack':
with open(lst + "_example_list") as src:
shutil.copyfileobj(src, dst)

compilerdir = os.path.join('..', '..', '..', '..', 'compiler', self.version,
'linux', 'compiler', 'lib', 'intel64_lin')
# IFACE_COMP_PART=gf gives the gfortran calling convention that FlexiBLAS expects
cmds = ["make libintel64 IFACE_COMP_PART=gf export=%s name=%s" % (
listfilename, os.path.join(flexiblasdir, 'libflexiblas_imkl_')) +
s for s in ['sequential threading=sequential',
'gnu_thread parallel=gnu',
'intel_thread parallel=intel SYSTEM_LIBS="-lm -ldl -L%s"' % compilerdir]]

for cmd in cmds:
res = run_cmd(cmd, log_all=True, simple=True)
if not res:
raise EasyBuildError("Building FlexiBLAS-compatible library (cmd: %s) failed", cmd)

def post_install_step(self):
"""
Install group libraries and interfaces (if desired).
Expand Down Expand Up @@ -342,6 +381,9 @@ def post_install_step(self):
if self.cfg['interfaces']:
self.build_mkl_fftw_interfaces(os.path.join(self.installdir, libdir))

if self.cfg['flexiblas']:
self.build_mkl_flexiblas(os.path.join(self.installdir, libdir, 'flexiblas'))

def get_mkl_fftw_interface_libs(self):
"""Returns list of library names produced by build_mkl_fftw_interfaces()"""

Expand Down Expand Up @@ -398,6 +440,10 @@ def sanity_check_step(self):
if self.cfg['interfaces']:
libs += self.get_mkl_fftw_interface_libs()

if self.cfg['flexiblas']:
libs += [os.path.join('flexiblas', 'libflexiblas_imkl_%s.so' % thread)
for thread in ['gnu_thread', 'intel_thread', 'sequential']]

if ver >= LooseVersion('10.3') and self.cfg['m32']:
raise EasyBuildError("Sanity check for 32-bit not implemented yet for IMKL v%s (>= 10.3)", self.version)

Expand Down Expand Up @@ -498,6 +544,8 @@ def make_module_req_guess(self):
'CPATH': cpath,
'PKG_CONFIG_PATH': pkg_config_path,
})
if self.cfg['flexiblas']:
guesses['FLEXIBLAS_LIBRARY_PATH'] = os.path.join(library_path[1], 'flexiblas')
else:
if self.cfg['m32']:
guesses.update({
Expand Down Expand Up @@ -532,4 +580,5 @@ def make_module_extra(self):
mklroot = os.path.join(self.installdir, 'mkl')

txt += self.module_generator.set_environment('MKLROOT', mklroot)

return txt