Skip to content
Merged
51 changes: 50 additions & 1 deletion easybuild/easyblocks/e/elpa.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,21 @@
@author: Kenneth Hoste (Ghent University)
"""
import os
from distutils.version import LooseVersion

import easybuild.tools.environment as env
from easybuild.easyblocks.generic.configuremake import ConfigureMake
from easybuild.framework.easyconfig import CUSTOM
from easybuild.toolchains.compiler.gcc import TC_CONSTANT_GCC
from easybuild.toolchains.compiler.inteliccifort import TC_CONSTANT_INTELCOMP
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.filetools import apply_regex_substitutions
from easybuild.tools.modules import get_software_root
from easybuild.tools.systemtools import get_cpu_features, get_shared_lib_ext
from easybuild.tools.toolchain.compiler import OPTARCH_GENERIC
from easybuild.tools.utilities import nub


ELPA_CPU_FEATURE_FLAGS = ['avx', 'avx2', 'avx512f', 'vsx', 'sse4_2']


Expand Down Expand Up @@ -176,6 +180,51 @@ def run_all_steps(self, *args, **kwargs):

return super(EB_ELPA, self).run_all_steps(*args, **kwargs)

def configure_step(self):
"""Configure step for ELPA"""

# Add nvidia GPU support if requested
cuda_root = get_software_root('CUDA')
self.log.info("Got cuda root: %s", cuda_root)
if cuda_root:
self.cfg.update('configopts', '--enable-nvidia-gpu')
self.cfg.update('configopts', '--with-cuda-path=%s' % cuda_root)
self.cfg.update('configopts', '--with-cuda-sdk-path=%s' % cuda_root)

cuda_cc = build_option('cuda_compute_capabilities') or self.cfg['cuda_compute_capabilities']
if not cuda_cc:
raise EasyBuildError('List of CUDA compute capabilities must be specified, either via '
'cuda_compute_capabilities easyconfig parameter or via '
'--cuda-compute-capabilities')

# ELPA's --with-NVIDIA-GPU-compute-capability only accepts a single architecture
if len(cuda_cc) != 1:
raise EasyBuildError('ELPA currently only supports specifying one CUDA architecture when '
'building. You specified cuda-compute-capabilities: %s', cuda_cc)
Comment on lines +200 to +203
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a hard error, or should we pick one (e.g. lowest) and throw a warning? I think that's how this is handled in a few other easyblocks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should assume we know what is best for the user here, so I'd personally prefer an error. That allows the user to pick by simply passing a single compute capability on the command line. If I know that only a single one is supported, I could decide to pick the highest and only run on nodes that support that architecture.

Copy link
Contributor Author

@casparvl casparvl Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(or, obviously, I could decide to pick the lowest and be able to run on any GPU node in that system. Just meant to say that both are valid choices :))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's something to say about both approaches,
but imho that discussion should not block this PR.

cuda_cc = cuda_cc[0]
cuda_cc_string = cuda_cc.replace('.', '')
self.cfg.update('configopts', '--with-NVIDIA-GPU-compute-capability=sm_%s' % cuda_cc_string)
self.log.info("Enabling nvidia GPU support for compute capability: %s", cuda_cc_string)
# There is a dedicated kernel for sm80, but only from version 2021.11.001 onwards
if float(cuda_cc) >= 8.0 and LooseVersion(self.version) >= LooseVersion('2021.11.001'):
self.cfg.update('configopts', '--enable-nvidia-sm80-gpu')

# From v2022.05.001 onwards, the config complains if CPP is not set, resulting in non-zero exit of configure
# C preprocessor to use for given comp_fam
cpp_dict = {
TC_CONSTANT_GCC: 'cpp',
TC_CONSTANT_INTELCOMP: 'cpp',
}
comp_fam = self.toolchain.comp_family()
if comp_fam in cpp_dict:
env.setvar('CPP', cpp_dict[comp_fam])
else:
raise EasyBuildError('ELPA EasyBlock does not know which C preprocessor to use for the '
'current compiler family (%s). Please add the correct preprocessor '
'for this compiler family to cpp_dict in the ELPA EasyBlock', comp_fam)

super(EB_ELPA, self).configure_step()

def patch_step(self, *args, **kwargs):
"""Patch manual_cpp script to avoid using hardcoded /usr/bin/python."""
super(EB_ELPA, self).patch_step(*args, **kwargs)
Expand Down