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 = { ...@@ -47,11 +47,22 @@ VETOED_INSTALLATIONS = {
'juwelsbooster': ['impi', 'impi-settings', 'BullMPI', 'BullMPI-settings'], 'juwelsbooster': ['impi', 'impi-settings', 'BullMPI', 'BullMPI-settings'],
'juwels': ['BullMPI', 'BullMPI-settings'], 'juwels': ['BullMPI', 'BullMPI-settings'],
'jurecadc': [''], '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'], 'jusuf': ['impi', 'impi-settings', 'BullMPI', 'BullMPI-settings'],
'hdfml': ['BullMPI', 'BullMPI-settings'], 'hdfml': ['BullMPI', 'BullMPI-settings'],
} }
TWEAKABLE_DEPENDENCIES = {
'UCX': 'default',
'CUDA': '11.5',
}
common_site_contact = 'Support <sc@fz-juelich.de>' common_site_contact = 'Support <sc@fz-juelich.de>'
# Also maintain a list of CUDA enabled compilers # Also maintain a list of CUDA enabled compilers
...@@ -106,8 +117,10 @@ def get_user_info(): ...@@ -106,8 +117,10 @@ def get_user_info():
if name and email: if name and email:
return [name, email] return [name, email]
else: else:
print_warning(f"\n'jutil' is not present and 'SITE_CONTACT_NAME' or 'SITE_CONTACT_EMAIL' are not defined\n" print_warning(
"Please defined both in your environment and try again\n") 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) exit(1)
else: else:
return ['CI user', 'ci_user@fz-juelich.de'] return ['CI user', 'ci_user@fz-juelich.de']
...@@ -183,62 +196,119 @@ def inject_site_contact(ec, site_contacts): ...@@ -183,62 +196,119 @@ def inject_site_contact(ec, site_contacts):
# ec[key] = value # ec[key] = value
return ec return ec
def parse_hook(ec, *args, **kwargs): def parse_hook(ec, *args, **kwargs):
"""Custom parse hook to manage installations intended for JSC systems.""" """Custom parse hook to manage installations intended for JSC systems."""
# First of all check if this should be installed # First of all check if this should be installed
installation_vetoer(ec) 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() ec_dict = ec.asdict()
# Compilers are are a family (in the Lmod sense) # Check where installations are going to go and add appropriate site contact
if ec.name in SUPPORTED_COMPILERS: # 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" key = "modluafooter"
value = 'family("compiler")' value = 'add_property("build","user")'
if key in ec_dict: if key in ec_dict:
if not value in ec_dict[key]: if not value in ec_dict[key]:
ec[key] = "\n".join([ec[key], value]) ec[key] = "\n".join([ec_dict[key], value])
else: else:
ec[key] = value ec[key] = value
ec.log.info("[parse hook] Injecting Lmod compiler family") ec.log.info("[parse hook] Injecting user as Lmod build property")
# Supported compilers should also be recursively unloaded # Inject the user
key = "recursive_module_unload" installer_name, installer_email = get_user_info()
if not key in ec_dict or ec_dict[key] is None: site_contacts = format_site_contact(
ec[key] = True installer_name, installer_email, default_contact=False)
ec.log.info( ec = inject_site_contact(ec, site_contacts)
"[parse hook] Injecting recursive module unloading for supported compiler"
) return ec
# Update the dict def inject_gpu_property(ec):
ec_dict = ec.asdict() ec_dict = ec.asdict()
# MPIs are a family (in the Lmod sense) and require to load mpi-settings # Check if CUDA is in the dependencies, if so add the GPU Lmod tag
if ec.name in SUPPORTED_MPIS and '/p/software' in install_path().lower(): if (
"CUDA" in [dep[0] for dep in iter(ec_dict["dependencies"])]
or ec_dict["toolchain"]["name"] in CUDA_ENABLED_TOOLCHAINS
):
key = "modluafooter" key = "modluafooter"
value = ''' value = 'add_property("arch","gpu")'
if not ( isloaded("mpi-settings") ) then
load("mpi-settings")
end
family("mpi")
'''
if key in ec_dict: if key in ec_dict:
if not value in ec_dict[key]: if not value in ec_dict[key]:
ec[key] = "\n".join([ec[key], value]) ec[key] = "\n".join([ec_dict[key], value])
else: else:
ec[key] = value ec[key] = value
ec.log.info( ec.log.info("[parse hook] Injecting gpu as Lmod arch property")
"[parse hook] Injecting Lmod mpi family and mpi-settings loading")
# Check if we need to use 'modaltsoftname' return ec
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],
)
def inject_hidden_property(ec):
ec_dict = ec.asdict()
# Check if the module should be installed as hidden # Check if the module should be installed as hidden
hidden_pkgs = os.getenv('EASYBUILD_HIDE_DEPS', '').split(',') hidden_pkgs = os.getenv('EASYBUILD_HIDE_DEPS', '').split(',')
if ec.name in hidden_pkgs: if ec.name in hidden_pkgs:
...@@ -249,76 +319,64 @@ family("mpi") ...@@ -249,76 +319,64 @@ family("mpi")
"[parse hook] Hiding software found in $EASYBUILD_HIDE_DEPS: %s", "[parse hook] Hiding software found in $EASYBUILD_HIDE_DEPS: %s",
ec.name, ec.name,
) )
return ec
# Update the dict def inject_modaltsoftname(ec):
ec_dict = ec.asdict() ec_dict = ec.asdict()
# Check if CUDA is in the dependencies, if so add the GPU Lmod tag # Check if we need to use 'modaltsoftname'
if ( if ec.name in REQUIRE_MODALTSOFTNAME:
"CUDA" in [dep[0] for dep in iter(ec_dict["dependencies"])] key = "modaltsoftname"
or ec_dict["toolchain"]["name"] in CUDA_ENABLED_TOOLCHAINS 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" 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 key in ec_dict:
if not value in ec_dict[key]: if not value in ec_dict[key]:
ec[key] = "\n".join([ec_dict[key], value]) ec[key] = "\n".join([ec[key], value])
else: else:
ec[key] = value 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() ec_dict = ec.asdict()
# Check where installations are going to go and add appropriate site contact # Compilers are are a family (in the Lmod sense)
# not sure of a fool-proof way to do this, let's just try a heuristic if ec.name in SUPPORTED_COMPILERS:
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" key = "modluafooter"
value = 'add_property("build","user")' value = 'family("compiler")'
if key in ec_dict: if key in ec_dict:
if not value in ec_dict[key]: if not value in ec_dict[key]:
ec[key] = "\n".join([ec_dict[key], value]) ec[key] = "\n".join([ec[key], value])
else: else:
ec[key] = value ec[key] = value
ec.log.info("[parse hook] Injecting user as Lmod build property") ec.log.info("[parse hook] Injecting Lmod compiler family")
# Inject the user # Supported compilers should also be recursively unloaded
installer_name, installer_email = get_user_info() key = "recursive_module_unload"
site_contacts = format_site_contact( if not key in ec_dict or ec_dict[key] is None:
installer_name, installer_email, default_contact=False) ec[key] = True
ec = inject_site_contact(ec, site_contacts) ec.log.info(
"[parse hook] Injecting recursive module unloading for supported compiler"
# 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 ...."
) )
return ec
def pre_ready_hook(self, *args, **kwargs): def pre_ready_hook(self, *args, **kwargs):
"When we are building something, do some checks for bad behaviour" "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 ...@@ -9,8 +9,6 @@ An open-source production grade communication framework for data centric
and high-performance applications and high-performance applications
""" """
site_contacts = 'Damian Alvarez <d.alvarez@fz-juelich.de>'
toolchain = SYSTEM toolchain = SYSTEM
toolchainopts = {'pic': True} toolchainopts = {'pic': True}
...@@ -31,7 +29,7 @@ osdependencies = [OS_PKG_IBVERBS_DEV] ...@@ -31,7 +29,7 @@ osdependencies = [OS_PKG_IBVERBS_DEV]
dependencies = [ dependencies = [
('zlib', '1.2.11'), ('zlib', '1.2.11'),
('numactl', '2.0.14'), ('numactl', '2.0.14'),
('CUDA', '11.4'), ('CUDA', '11.5'),
] ]
configopts = '--with-verbs ' # Build OpenFabrics support 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