Skip to content

Commit

Permalink
DEBUG only {2023.06,2023a} PyTorch-bundle v2.1.2
Browse files Browse the repository at this point in the history
- PR to help debugging various issues when building PyTorch-bundle
- includes a fix for `find_library` provided by `ctypes.util` which prevented
  importing `sndfile`
- includes a fix for `aarch64/generic` where importing `sentencepiece` lead to
  the error `libtcmalloc_minimal.so.4: cannot allocate memory in static TLS block`
- includes a fix for the extension `torchvision` where some library was not
  compiled with `jpeg` support, hence some tests failed
  • Loading branch information
truib committed Jun 12, 2024
1 parent aba8ff5 commit 6f8662e
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 1 deletion.
6 changes: 6 additions & 0 deletions EESSI-install-software.sh
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ if command_exists "nvidia-smi"; then
${EESSI_PREFIX}/scripts/gpu_support/nvidia/link_nvidia_host_libraries.sh
fi

# Install extra software that is needed (e.g., for providing a custom ctypes
# library when needed)
cd ${TOPDIR}/scripts/extra
./install_extra_packages.sh --temp-dir /tmp/temp --easystack eessi-2023.06-extra-packages.yml
cd ${TOPDIR}

# use PR patch file to determine in which easystack files stuff was added
changed_easystacks=$(cat ${pr_diff} | grep '^+++' | cut -f2 -d' ' | sed 's@^[a-z]/@@g' | grep '^easystacks/.*yml$' | egrep -v 'known-issues|missing')
if [ -z "${changed_easystacks}" ]; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ easyconfigs:
- GATK-4.5.0.0-GCCcore-12.3.0-Java-17.eb
- WhatsHap-2.2-foss-2023a.eb
- BLAST+-2.14.1-gompi-2023a.eb:
options:
options:
from-pr: 20784
- Valgrind-3.21.0-gompi-2023a.eb
- OrthoFinder-2.5.5-foss-2023a.eb
- PyTorch-bundle-2.1.2-foss-2023a.eb:
# see https://github.com/easybuilders/easybuild-easyconfigs/pull/20382
options:
from-pr: 20382
125 changes: 125 additions & 0 deletions eb_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import easybuild.tools.environment as env
from easybuild.easyblocks.generic.configuremake import obtain_config_guess
from easybuild.easyblocks.python import EXTS_FILTER_PYTHON_PACKAGES
from easybuild.framework.easyconfig.constants import EASYCONFIG_CONSTANTS
from easybuild.tools.build_log import EasyBuildError, print_msg
from easybuild.tools.config import build_option, update_build_option
Expand Down Expand Up @@ -214,6 +215,30 @@ def parse_hook_fontconfig_add_fonts(ec, eprefix):
raise EasyBuildError("fontconfig-specific hook triggered for non-fontconfig easyconfig?!")


def parse_hook_librosa_custom_ctypes(ec, *args, **kwargs):
"""
Add exts_filter to soundfile extension in exts_list
"""
if ec.name == 'librosa' and ec.version in ('0.10.1',):
ec_dict = ec.asdict()
eessi_software_path = get_eessi_envvar('EESSI_SOFTWARE_PATH')
custom_ctypes_path = os.path.join(eessi_software_path, "software", "custom_ctypes", "1.2")
ebpythonprefixes = "EBPYTHONPREFIXES=%s" % custom_ctypes_path
exts_list_new = []
for item in ec_dict['exts_list']:
if item[0] == 'soundfile':
ext_dict = item[2]
ext_dict['exts_filter'] = (ebpythonprefixes + ' ' + EXTS_FILTER_PYTHON_PACKAGES[0],
EXTS_FILTER_PYTHON_PACKAGES[1])
exts_list_new.append((item[0], item[1], ext_dict))
else:
exts_list_new.append(item)
ec['exts_list'] = exts_list_new
print_msg("New exts_list: '%s'", ec['exts_list'])
else:
raise EasyBuildError("librosa/0.10.1-specific hook triggered for non-librosa/0.10.1 easyconfig?!")


def parse_hook_openblas_relax_lapack_tests_num_errors(ec, eprefix):
"""Relax number of failing numerical LAPACK tests for aarch64/neoverse_v1 CPU target for OpenBLAS < 0.3.23"""
cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR')
Expand Down Expand Up @@ -253,6 +278,46 @@ def parse_hook_pybind11_replace_catch2(ec, eprefix):
build_deps[idx] = (catch2_name, catch2_version)


def parse_hook_pytorch_bundle_torchvision_setenv(ec, eprefix):
"""
Set TORCHVISION_{INCLUDE,LIBRARY}, initially for non-CUDA version only
"""
if ec.name == 'PyTorch-bundle' and ec.version in ['2.1.2']:
if not hasattr(ec, 'versionsuffix') or (ec.versionsuffix and not 'CUDA' in ec.versionsuffix):
print_msg("parse_hook for PyTorch-bundle without CUDA: extslist '%s'", ec['exts_list'])
print_msg("New exts_list: '%s'", ec['exts_list'])
ec_dict = ec.asdict()
cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR')
eessi_software_path = get_eessi_envvar('EESSI_SOFTWARE_PATH')
libpng_root = os.path.join(eessi_software_path, "software", "libpng", "1.6.39-GCCcore-12.3.0")
libpng_include = os.path.join(libpng_root, 'include')
libpng_lib = os.path.join(libpng_root, 'lib')
libjpeg_turbo_root = os.path.join(eessi_software_path, "software", "libjpeg-turbo", "2.1.5.1-GCCcore-12.3.0")
libjpeg_turbo_include = os.path.join(libjpeg_turbo_root, 'include')
libjpeg_turbo_lib = os.path.join(libjpeg_turbo_root, 'lib')
exts_list_new = []
torchvision_include = 'export TORCHVISION_INCLUDE=%s:%s' % (libpng_include, libjpeg_turbo_include)
torchvision_library = 'export TORCHVISION_LIBRARY=%s:%s' % (libpng_lib, libjpeg_turbo_lib)
for item in ec_dict['exts_list']:
if item[0] != 'torchvision':
exts_list_new.append(item)
else:
ext_dict = item[2]
if 'preinstallopts' in ext_dict:
raise EasyBuildError("found value for 'preinstallopts' for extension 'torchvision',"
" but expected NONE")
else:
# add preinstallopts
ext_dict['preinstallopts'] = torchvision_include + ' && ' + torchvision_library + ' && '
exts_list_new.append((item[0], item[1], ext_dict))
ec['exts_list'] = exts_list_new
print_msg("New exts_list: '%s'", ec['exts_list'])
else:
print_msg("parse_hook for PyTorch-bundle for CUDA -> leaving preinstallopts unchanged")
else:
raise EasyBuildError("PyTorch-bundle-specific hook triggered for non-PyTorch-bundle easyconfig?!")


def parse_hook_qt5_check_qtwebengine_disable(ec, eprefix):
"""
Disable check for QtWebEngine in Qt5 as workaround for problem with determining glibc version.
Expand All @@ -266,6 +331,30 @@ def parse_hook_qt5_check_qtwebengine_disable(ec, eprefix):
raise EasyBuildError("Qt5-specific hook triggered for non-Qt5 easyconfig?!")


def parse_hook_sentencepiece_disable_tcmalloc_aarch64(ec, eprefix):
"""
Disable using TC_Malloc on 'aarch64/generic'
"""
cpu_target = get_eessi_envvar('EESSI_SOFTWARE_SUBDIR')
if ec.name == 'SentencePiece' and ec.version in ['0.2.0']:
if cpu_target == CPU_TARGET_AARCH64_GENERIC:
print_msg("parse_hook for SentencePiece: OLD '%s'", ec['components'])
new_components = []
for item in ec['components']:
if item[2]['easyblock'] == 'CMakeMake':
new_item = item[2]
new_item['configopts'] = '-DSPM_ENABLE_TCMALLOC=OFF'
new_components.append((item[0], item[1], new_item))
else:
new_components.append(item)
ec['components'] = new_components
print_msg("parse_hook for SentencePiece: NEW '%s'", ec['components'])
else:
print_msg("parse_hook for SentencePiece on %s -> leaving configopts unchanged", cpu_target)
else:
raise EasyBuildError("SentencePiece-specific hook triggered for non-SentencePiece easyconfig?!")


def parse_hook_ucx_eprefix(ec, eprefix):
"""Make UCX aware of compatibility layer via additional configuration options."""
if ec.name == 'UCX':
Expand Down Expand Up @@ -659,14 +748,46 @@ def inject_gpu_property(ec):
return ec


def pre_module_hook(self, *args, **kwargs):
"""Main pre-module-check hook: trigger custom functions based on software name."""
if self.name in PRE_MODULE_HOOKS:
PRE_MODULE_HOOKS[self.name](self, *args, **kwargs)


def pre_module_hook_librosa_augment_modluafooter(self, *args, **kwargs):
"""
Add EBPYTHONPREFIXES to modluafooter
"""
if self.name == 'librosa' and self.version == '0.10.1':
eessi_software_path = get_eessi_envvar('EESSI_SOFTWARE_PATH')
custom_ctypes_path = os.path.join(eessi_software_path, "software", "custom_ctypes", "1.2")
key = 'modluafooter'
values = ['prepend_path("EBPYTHONPREFIXES","%s")' % (custom_ctypes_path)]
print_msg("Adding '%s' to modluafooter", values[0])
if not key in self.cfg:
self.cfg[key] = '\n'.join(values)
else:
new_value = self.cfg[key]
for value in values:
if not value in new_value:
new_value = '\n'.join([new_value, value])
self.cfg[key] = new_value
print_msg("Full modluafooter is '%s'", self.cfg[key])
else:
raise EasyBuildError("librosa/0.10.1-specific hook triggered for non-librosa/0.10.1 easyconfig?!")


PARSE_HOOKS = {
'casacore': parse_hook_casacore_disable_vectorize,
'CGAL': parse_hook_cgal_toolchainopts_precise,
'fontconfig': parse_hook_fontconfig_add_fonts,
'LAMMPS': parse_hook_lammps_remove_deps_for_CI_aarch64,
'librosa': parse_hook_librosa_custom_ctypes,
'OpenBLAS': parse_hook_openblas_relax_lapack_tests_num_errors,
'pybind11': parse_hook_pybind11_replace_catch2,
'PyTorch-bundle': parse_hook_pytorch_bundle_torchvision_setenv,
'Qt5': parse_hook_qt5_check_qtwebengine_disable,
'SentencePiece': parse_hook_sentencepiece_disable_tcmalloc_aarch64,
'UCX': parse_hook_ucx_eprefix,
}

Expand Down Expand Up @@ -710,3 +831,7 @@ def inject_gpu_property(ec):
POST_SANITYCHECK_HOOKS = {
'CUDA': post_sanitycheck_cuda,
}

PRE_MODULE_HOOKS = {
'librosa': pre_module_hook_librosa_augment_modluafooter,
}
29 changes: 29 additions & 0 deletions scripts/extra/custom_ctypes-1.2.eb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
##
# This is a contribution from the NESSI project
# Homepage: https://documentation.sigma2.no
#
# Authors:: Thomas Roeblitz <[email protected]>
# License:: GPL-2.0-only
#
##

easyblock = 'Tarball'

name = 'custom_ctypes'
version = '1.2'

homepage = 'https://github.com/ComputeCanada/custom_ctypes'
description = """custum_ctypes is a small Python package to fix the discovery of libraries with Python's ctypes module. It changes the behavior of find_library to return absolute paths to shared objects rather than just the names."""

toolchain = SYSTEM

source_urls = ['https://github.com/ComputeCanada/custom_ctypes/archive/refs/tags']
sources = ['%(version)s.tar.gz']
checksums = ['3b30ce633c6a329169f2b10ff24b8eaaeef3fa208a66cdacdb53c22f02a88d9b']

sanity_check_paths = {
'files': ['README.md'],
'dirs': ['lib'],
}

moduleclass = 'lib'
2 changes: 2 additions & 0 deletions scripts/extra/eessi-2023.06-extra-packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
easyconfigs:
- custom_ctypes-1.2.eb
95 changes: 95 additions & 0 deletions scripts/extra/install_extra_packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env bash

# This script can be used to install extra packages under ${EESSI_SOFTWARE_PATH}

# some logging
echo ">>> Running ${BASH_SOURCE}"

# Initialise our bash functions
TOPDIR=$(dirname $(realpath ${BASH_SOURCE}))
source "${TOPDIR}"/../utils.sh

# Function to display help message
show_help() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --help Display this help message"
echo " -e, --easystack EASYSTACKFILE Easystack file which specifies easyconfigs to be installed."
echo " -t, --temp-dir /path/to/tmpdir Specify a location to use for temporary"
echo " storage during the installation"
}

# Initialize variables
TEMP_DIR=
EASYSTACK_FILE=

# Parse command-line options
while [[ $# -gt 0 ]]; do
case "$1" in
--help)
show_help
exit 0
;;
-e|--easystack)
if [ -n "$2" ]; then
EASYSTACK_FILE="$2"
shift 2
else
echo "Error: Argument required for $1"
show_help
exit 1
fi
;;
-t|--temp-dir)
if [ -n "$2" ]; then
TEMP_DIR="$2"
shift 2
else
echo "Error: Argument required for $1"
show_help
exit 1
fi
;;
*)
show_help
fatal_error "Error: Unknown option: $1"
;;
esac
done

if [[ -z ${EASYSTACK_FILE} ]]; then
show_help
fatal_error "Error: need to specify easystack file"
fi

# Make sure NESSI is initialised
check_eessi_initialised

# As an installation location just use $EESSI_SOFTWARE_PATH
export NESSI_CVMFS_INSTALL=${EESSI_SOFTWARE_PATH}

# we need a directory we can use for temporary storage
if [[ -z "${TEMP_DIR}" ]]; then
tmpdir=$(mktemp -d)
else
mkdir -p ${TEMP_DIR}
tmpdir=$(mktemp -d --tmpdir=${TEMP_DIR} extra.XXX)
if [[ ! -d "$tmpdir" ]] ; then
fatal_error "Could not create directory ${tmpdir}"
fi
fi
echo "Created temporary directory '${tmpdir}'"
export WORKING_DIR=${tmpdir}

# load EasyBuild
ml EasyBuild

# load NESSI-extend/2023.06-easybuild
ml NESSI-extend/2023.06-easybuild

eb --show-config

eb --easystack ${EASYSTACK_FILE} --robot

# clean up tmpdir
rm -rf "${tmpdir}"

0 comments on commit 6f8662e

Please sign in to comment.