Skip to content
Snippets Groups Projects
Commit 46ff2c7b authored by Damian Alvarez's avatar Damian Alvarez
Browse files

To support the overriding of UCX/default, so we can overlap with

upstream better and have an UCX wrapper that we can update transparently
parent 8ccb7be5
No related branches found
No related tags found
No related merge requests found
......@@ -47,11 +47,22 @@ VETOED_INSTALLATIONS = {
'juwelsbooster': ['impi', 'impi-settings', 'BullMPI', 'BullMPI-settings'],
'juwels': ['BullMPI', 'BullMPI-settings'],
'jurecadc': [''],
'jurecabooster': ['OpenMPI', 'OpenMPI-settings', 'CUDA', 'nvidia-driver', 'UCX', 'NVHPC', 'BullMPI', 'BullMPI-settings'],
'jurecabooster': [
'OpenMPI', 'OpenMPI-settings',
'CUDA', 'nvidia-driver',
'UCX', 'UCX-settings',
'NCCL', 'NCCL-settings', 'NVHPC',
'BullMPI', 'BullMPI-settings'
],
'jusuf': ['impi', 'impi-settings', 'BullMPI', 'BullMPI-settings'],
'hdfml': ['BullMPI', 'BullMPI-settings'],
}
TWEAKABLE_DEPENDENCIES = {
'UCX': 'default',
'CUDA': '11.5',
}
common_site_contact = 'Support <sc@fz-juelich.de>'
# Also maintain a list of CUDA enabled compilers
......@@ -106,8 +117,10 @@ def get_user_info():
if name and email:
return [name, email]
else:
print_warning(f"\n'jutil' is not present and 'SITE_CONTACT_NAME' or 'SITE_CONTACT_EMAIL' are not defined\n"
"Please defined both in your environment and try again\n")
print_warning(
f"\n'jutil' is not present and 'SITE_CONTACT_NAME' or 'SITE_CONTACT_EMAIL' are not defined\n"
"Please defined both in your environment and try again\n"
)
exit(1)
else:
return ['CI user', 'ci_user@fz-juelich.de']
......@@ -183,62 +196,119 @@ def inject_site_contact(ec, site_contacts):
# ec[key] = value
return ec
def parse_hook(ec, *args, **kwargs):
"""Custom parse hook to manage installations intended for JSC systems."""
# First of all check if this should be installed
installation_vetoer(ec)
# Process compiler options
ec = inject_compiler_features(ec)
# Process MPI options
ec = inject_mpi_features(ec)
# Change module name if applicable
ec = inject_modaltsoftname(ec)
ec = inject_hidden_property(ec)
ec = inject_gpu_property(ec)
ec = inject_site_contact_and_user_labels(ec)
ec = tweak_dependencies(ec)
# If we are parsing we are not searching, in this case if the easyconfig is
# located in the search path, warn that it's dependencies will (most probably)
# not be resolved
if build_option("robot"):
search_paths = build_option("search_paths") or []
robot_paths = list(
set(build_option("robot_path") + build_option("robot")))
if ec.path:
ec_dir_path = os.path.dirname(os.path.abspath(ec.path))
else:
ec_dir_path = ''
if any(search_path in ec_dir_path for search_path in search_paths) and not any(
robot_path in ec_dir_path for robot_path in robot_paths
):
raise EasyBuildError(
"\nYou are attempting to install an easyconfig distributed with "
"EasyBuild but are not properly configured to resolve dependencies "
"for this case. Please add additonal options:\n"
" eb --robot=$EASYBUILD_ROBOT:$EBROOTEASYBUILD/easybuild/easyconfigs --try-update-deps ...."
)
def tweak_dependencies(ec):
for dep_type in ["dependencies", "builddependencies"]:
dependencies = ec[dep_type]
# Check for dependencies to be tweaked. This assumes simply that the version is
# being overwritten
for dep_to_tweak in TWEAKABLE_DEPENDENCIES:
for dep in dependencies:
if dep_to_tweak in dep[0]:
list_dep = list(dep)
list_dep[1] = TWEAKABLE_DEPENDENCIES[dep_to_tweak]
dependencies[dependencies.index(dep)] = tuple(list_dep)
ec[dep_type] = dependencies
return ec
def inject_site_contact_and_user_labels(ec):
ec_dict = ec.asdict()
# Compilers are are a family (in the Lmod sense)
if ec.name in SUPPORTED_COMPILERS:
# Check where installations are going to go and add appropriate site contact
# not sure of a fool-proof way to do this, let's just try a heuristic
site_contacts = None
# Non-user installation
if '/p/software' in install_path().lower():
if 'swmanage' in os.getenv('USER'):
site_contacts = common_site_contact
else:
installer_name, installer_email = get_user_info()
site_contacts = format_site_contact(
installer_name, installer_email)
# Inject the user
ec = inject_site_contact(ec, site_contacts)
# User installation
else:
# Tag the build as a user build
key = "modluafooter"
value = 'family("compiler")'
value = 'add_property("build","user")'
if key in ec_dict:
if not value in ec_dict[key]:
ec[key] = "\n".join([ec[key], value])
ec[key] = "\n".join([ec_dict[key], value])
else:
ec[key] = value
ec.log.info("[parse hook] Injecting Lmod compiler family")
# Supported compilers should also be recursively unloaded
key = "recursive_module_unload"
if not key in ec_dict or ec_dict[key] is None:
ec[key] = True
ec.log.info(
"[parse hook] Injecting recursive module unloading for supported compiler"
)
ec.log.info("[parse hook] Injecting user as Lmod build property")
# Inject the user
installer_name, installer_email = get_user_info()
site_contacts = format_site_contact(
installer_name, installer_email, default_contact=False)
ec = inject_site_contact(ec, site_contacts)
return ec
# Update the dict
def inject_gpu_property(ec):
ec_dict = ec.asdict()
# MPIs are a family (in the Lmod sense) and require to load mpi-settings
if ec.name in SUPPORTED_MPIS and '/p/software' in install_path().lower():
# Check if CUDA is in the dependencies, if so add the GPU Lmod tag
if (
"CUDA" in [dep[0] for dep in iter(ec_dict["dependencies"])]
or ec_dict["toolchain"]["name"] in CUDA_ENABLED_TOOLCHAINS
):
key = "modluafooter"
value = '''
if not ( isloaded("mpi-settings") ) then
load("mpi-settings")
end
family("mpi")
'''
value = 'add_property("arch","gpu")'
if key in ec_dict:
if not value in ec_dict[key]:
ec[key] = "\n".join([ec[key], value])
ec[key] = "\n".join([ec_dict[key], value])
else:
ec[key] = value
ec.log.info(
"[parse hook] Injecting Lmod mpi family and mpi-settings loading")
ec.log.info("[parse hook] Injecting gpu as Lmod arch property")
# Check if we need to use 'modaltsoftname'
if ec.name in REQUIRE_MODALTSOFTNAME:
key = "modaltsoftname"
if not key in ec_dict or ec_dict[key] is None:
ec[key] = REQUIRE_MODALTSOFTNAME[ec.name]
ec.log.info(
"[parse hook] Injecting modaltsoftname '%s' for '%s'",
key,
REQUIRE_MODALTSOFTNAME[ec.name],
)
return ec
def inject_hidden_property(ec):
ec_dict = ec.asdict()
# Check if the module should be installed as hidden
hidden_pkgs = os.getenv('EASYBUILD_HIDE_DEPS', '').split(',')
if ec.name in hidden_pkgs:
......@@ -249,76 +319,64 @@ family("mpi")
"[parse hook] Hiding software found in $EASYBUILD_HIDE_DEPS: %s",
ec.name,
)
return ec
# Update the dict
def inject_modaltsoftname(ec):
ec_dict = ec.asdict()
# Check if CUDA is in the dependencies, if so add the GPU Lmod tag
if (
"CUDA" in [dep[0] for dep in iter(ec_dict["dependencies"])]
or ec_dict["toolchain"]["name"] in CUDA_ENABLED_TOOLCHAINS
):
# Check if we need to use 'modaltsoftname'
if ec.name in REQUIRE_MODALTSOFTNAME:
key = "modaltsoftname"
if not key in ec_dict or ec_dict[key] is None:
ec[key] = REQUIRE_MODALTSOFTNAME[ec.name]
ec.log.info(
"[parse hook] Injecting modaltsoftname '%s' for '%s'",
key,
REQUIRE_MODALTSOFTNAME[ec.name],
)
return ec
def inject_mpi_features(ec):
ec_dict = ec.asdict()
# MPIs are a family (in the Lmod sense) and require to load mpi-settings
if ec.name in SUPPORTED_MPIS and '/p/software' in install_path().lower():
key = "modluafooter"
value = 'add_property("arch","gpu")'
value = '''
if not ( isloaded("mpi-settings") ) then
load("mpi-settings")
end
family("mpi")
'''
if key in ec_dict:
if not value in ec_dict[key]:
ec[key] = "\n".join([ec_dict[key], value])
ec[key] = "\n".join([ec[key], value])
else:
ec[key] = value
ec.log.info("[parse hook] Injecting gpu as Lmod arch property")
ec.log.info(
"[parse hook] Injecting Lmod mpi family and mpi-settings loading")
# Update the dict
return ec
def inject_compiler_features(ec):
ec_dict = ec.asdict()
# Check where installations are going to go and add appropriate site contact
# not sure of a fool-proof way to do this, let's just try a heuristic
site_contacts = None
# Non-user installation
if '/p/software' in install_path().lower():
if 'swmanage' in os.getenv('USER'):
site_contacts = common_site_contact
else:
installer_name, installer_email = get_user_info()
site_contacts = format_site_contact(
installer_name, installer_email)
# Inject the user
ec = inject_site_contact(ec, site_contacts)
# User installation
else:
# Tag the build as a user build
# Compilers are are a family (in the Lmod sense)
if ec.name in SUPPORTED_COMPILERS:
key = "modluafooter"
value = 'add_property("build","user")'
value = 'family("compiler")'
if key in ec_dict:
if not value in ec_dict[key]:
ec[key] = "\n".join([ec_dict[key], value])
ec[key] = "\n".join([ec[key], value])
else:
ec[key] = value
ec.log.info("[parse hook] Injecting user as Lmod build property")
# Inject the user
installer_name, installer_email = get_user_info()
site_contacts = format_site_contact(
installer_name, installer_email, default_contact=False)
ec = inject_site_contact(ec, site_contacts)
# If we are parsing we are not searching, in this case if the easyconfig is
# located in the search path, warn that it's dependencies will (most probably)
# not be resolved
if build_option("robot"):
search_paths = build_option("search_paths") or []
robot_paths = list(
set(build_option("robot_path") + build_option("robot")))
if ec.path:
ec_dir_path = os.path.dirname(os.path.abspath(ec.path))
else:
ec_dir_path = ''
if any(search_path in ec_dir_path for search_path in search_paths) and not any(
robot_path in ec_dir_path for robot_path in robot_paths
):
raise EasyBuildError(
"\nYou are attempting to install an easyconfig distributed with "
"EasyBuild but are not properly configured to resolve dependencies "
"for this case. Please add additonal options:\n"
" eb --robot=$EASYBUILD_ROBOT:$EBROOTEASYBUILD/easybuild/easyconfigs --try-update-deps ...."
ec.log.info("[parse hook] Injecting Lmod compiler family")
# Supported compilers should also be recursively unloaded
key = "recursive_module_unload"
if not key in ec_dict or ec_dict[key] is None:
ec[key] = True
ec.log.info(
"[parse hook] Injecting recursive module unloading for supported compiler"
)
return ec
def pre_ready_hook(self, *args, **kwargs):
"When we are building something, do some checks for bad behaviour"
......
......@@ -9,8 +9,6 @@ An open-source production grade communication framework for data centric
and high-performance applications
"""
site_contacts = 'Damian Alvarez <d.alvarez@fz-juelich.de>'
toolchain = SYSTEM
toolchainopts = {'pic': True}
......@@ -31,7 +29,7 @@ osdependencies = [OS_PKG_IBVERBS_DEV]
dependencies = [
('zlib', '1.2.11'),
('numactl', '2.0.14'),
('CUDA', '11.4'),
('CUDA', '11.5'),
]
configopts = '--with-verbs ' # Build OpenFabrics support
......
easyblock = 'ConfigureMake'
name = 'UCX'
version = 'default'
local_realversion = '1.11.2'
homepage = 'https://www.openucx.org/'
description = """Unified Communication X
An open-source production grade communication framework for data centric
and high-performance applications
"""
toolchain = SYSTEM
toolchainopts = {'pic': True}
source_urls = ['https://github.com/openucx/ucx/releases/download/v%(local_realversion)s']
sources = ['%%(namelower)s-%s.tar.gz' % local_realversion]
checksums = [
'deebf86a5344fc2bd9e55449f88c650c4514928592807c9bc6fe4190e516c6df', # ucx-1.11.2.tar.gz
]
builddependencies = [
('binutils', '2.37'),
('Autotools', '20210726'),
('pkg-config', '0.29.2'),
]
osdependencies = [OS_PKG_IBVERBS_DEV]
dependencies = [
('zlib', '1.2.11'),
('numactl', '2.0.14'),
('CUDA', '11.5'),
]
configopts = '--with-verbs ' # Build OpenFabrics support
configopts += '--without-java '
configopts += '--disable-doxygen-doc '
# Enable machine-specific optimizations, default: NO
configopts += '--enable-optimizations '
# configopts += '--enable-tuning ' # Enable parameter tuning in run-time, default: NO
# Enable thread support in UCP and UCT, default: NO
configopts += '--enable-mt '
configopts += '--disable-debug '
configopts += '--disable-logging '
configopts += '--disable-assertions '
configopts += '--disable-params-check '
configopts += '--disable-dependency-tracking '
configopts += '--with-cuda=$EBROOTCUDA '
configopts += '--enable-cma ' # Enable Cross Memory Attach
# Compile with IB Reliable Connection support
configopts += '--with-rc '
# Compile with IB Unreliable Datagram support
configopts += '--with-ud '
# Compile with IB Dynamic Connection support
configopts += '--with-dc '
configopts += '--with-mlx5-dv ' # Compile with mlx5 Direct Verbs support
configopts += '--with-ib-hw-tm ' # Compile with IB Tag Matching support
configopts += '--with-dm ' # Compile with Device Memory support
configopts += '--with-avx ' # Compile with AVX
configopts += '--with-gdrcopy ' # Compile with GDRCopy
# Compile without IB Connection Manager support
configopts += '--without-cm '
buildopts = 'V=1'
sanity_check_paths = {
'files': ['bin/ucx_info', 'bin/ucx_perftest', 'bin/ucx_read_profile'],
'dirs': ['include', 'lib', 'share']
}
sanity_check_commands = ["ucx_info -d"]
moduleclass = 'system'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment