Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use libucx wheels #1041

Merged
merged 36 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1b7399a
use libucx wheels
jameslamb May 6, 2024
cbb283a
keep libucp
jameslamb May 6, 2024
875d582
get all dependencies via conda
jameslamb May 6, 2024
14d0233
ignore libucx dependency for conda packages
jameslamb May 6, 2024
2f030df
upload artifacts
jameslamb May 6, 2024
5541ee1
replace suffix for libucx
jameslamb May 6, 2024
dc74edd
uncomment uploads again
jameslamb May 6, 2024
2b4b6e3
maybe installation of the library itself can be skipped on readthedocs
jameslamb May 6, 2024
f7098fe
dlopen() earlier
jameslamb May 6, 2024
e424eb3
add build dpeendency too, remove system installations
jameslamb May 6, 2024
0a397f0
install is necessary for docs builds
jameslamb May 6, 2024
c8d91ca
fix conda deps, try to fix readthedocs builds
jameslamb May 6, 2024
acecf8e
fix libucx replacement in pyproject.toml
jameslamb May 6, 2024
e6acd0c
fix lib paths (still not to update rpath/runpath)
jameslamb May 6, 2024
f8f25c9
remove debugging stuff, switch to ImportError
jameslamb May 7, 2024
0c2234c
Merge branch 'branch-0.38' into ucx-wheels
jameslamb May 7, 2024
9825f82
Update dependencies.yaml
jameslamb May 7, 2024
9bd984c
Update conda/recipes/ucx-py/meta.yaml
jameslamb May 7, 2024
0523ba1
make build-time search for libucx insensitive to its internal layout
jameslamb May 8, 2024
c60800f
grammar
jameslamb May 8, 2024
91cbdf5
test with PIP_NO_DEPENDENCIES
jameslamb May 8, 2024
95da3ad
try an empty commit... maybe RTD doesnt apply environment variable up…
jameslamb May 8, 2024
327e93e
try with PIP_NO_BUILD_ISOLATION
jameslamb May 8, 2024
63976f2
just put a real dependency in pyproject.toml
jameslamb May 8, 2024
72596ae
build and run
jameslamb May 8, 2024
1146231
please
jameslamb May 8, 2024
5046584
another empty commit to test removing env variables from the RTD UI
jameslamb May 8, 2024
5c90c8e
catch more issues
jameslamb May 8, 2024
f1f949d
restore CPU support
jameslamb May 8, 2024
6723bae
remove try-catch for no-GPU settings
jameslamb May 10, 2024
ca60927
exclude libucs_signal too
jameslamb May 10, 2024
fb12aa3
remove ucx from docs conda env
jameslamb May 10, 2024
eba110f
use the headers from the libucx wheels too
jameslamb May 10, 2024
fb022ee
restore unsuffixed dependencies in pyproject.toml
jameslamb May 10, 2024
37dbad6
run patching script earlier on docs builds
jameslamb May 10, 2024
e2cffe3
catch run dependencies too
jameslamb May 10, 2024
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ dask-worker-space
__pytestcache__
__pycache__
*.egg-info/
final_dist/
dist/
.vscode

*.sw[po]

*.whl
8 changes: 3 additions & 5 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ build:
os: "ubuntu-22.04"
tools:
python: "mambaforge-22.9"

python:
install:
- method: pip
path: .
jobs:
post_checkout:
- bash ci/build_docs_pre_install.sh
Copy link
Member Author

Choose a reason for hiding this comment

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

There is no pip-installable library libucx... it needs to be either libucx-cu11 or libucx-cu12.

Readthedocs builds are installing directly from the pyproject.toml checked into source control, which
doesn't have those suffixes added.

ucx-py/.readthedocs.yml

Lines 8 to 11 in 03c864b

python:
install:
- method: pip
path: .

Resulting in this:

INFO: pip is looking at multiple versions of ucx-py to determine which version is compatible with other requirements. This could take a while.
ERROR: Could not find a version that satisfies the requirement libucx<1.16,>=1.15.0 (from ucx-py) (from versions: none)
ERROR: No matching distribution found for libucx<1.16,>=1.15.0

(example build link)

readthedocs doesn't allow customizing the pip install with arbitrary flags, e.g. by adding --no-deps (docs).

So I think this pre-install script to fix the suffixes is the best option to keep those builds working. For more details on how it works, see https://docs.readthedocs.io/en/stable/build-customization.html.

This comment was marked as resolved.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, I hadn't considered trying to get this into the conda environment file that way!

But I don't think that will work. conda converts the pip: section in an env.yaml into a requirements.txt, and you can only supply arguments that'd be valid in a requirements file passed to pip.

various forms of that that I tried (click me)

There are some issues tracking the request "forward custom flags to pip in conda environments" but none have resulted in changes to conda:

That means it's not possible to include arguments like --no-deps.

# env.yaml
name: delete-me
channels:
- conda-forge
dependencies:
- pip
- pip:
  - --no-deps -e ./
conda env create --name delete-me --file ./env.yaml

yields the following

Installing pip dependencies: - Ran pip subprocess with arguments:
['/raid/jlamb/miniforge/envs/delete-me/bin/python', '-m', 'pip', 'install', '-U', '-r', '/raid/jlamb/repos/ucx-py/condaenv.p9aa8j_k.requirements.txt', '--exists-action=b']
Pip subprocess output:

Pip subprocess error:
Usage: __main__.py [options]

ERROR: Invalid requirement: --no-deps -e ./
__main__.py: error: no such option: --no-deps

And without that --no-deps, conda tries to install all the dependencies of the package, resulting in

Pip subprocess error:
  error: subprocess-exited-with-error
  
  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [4 lines of output]
      Collecting cython>=3.0.0
        Using cached Cython-3.0.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.2 kB)
      ERROR: Could not find a version that satisfies the requirement libucx==1.15.0 (from versions: none)
      ERROR: No matching distribution found for libucx==1.15.0
      [end of output]

The only other thing I can think of is setting environment variable PIP_NO_DEPS=true in the build environment. I tried that using conda's support for environment variables (docs), but I don't think those affect the build... just the environment's activation.

name: delete-me
channels:
- conda-forge
dependencies:
- pip
- pip:
  - -e ./
variables:
- PIP_NO_DEPS: "true"

I see 2 options for this:

I think that environment variable option would be preferable, actually. This project has a small number of top-level dependencies, keeping the necessary ones in the conda environment file isn't a big lift. @vyasr what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

I don't have a preference, but I can set PIP_NO_DEPS=true if you two agree that's the preferred way.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, that seems a bit cleaner to me.

Did you try PIP_NO_DEPENDENCIES? I don't remember which is the right name (or maybe both work), and also the behavior of true/false for pip's *_NO_* variables can be confusing so it's worth double-checking all the options with the setting that you proposed in the env.yaml before we set this on RTD. If all else fails, though, I'm fine with setting on RTD.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ahhhhh I forgot that PIP_NO_DEPENDENCIES does not stop pip install from trying to download build dependencies.

Processing /home/docs/checkouts/readthedocs.org/user_builds/ucx-py/checkouts/1041
  Installing build dependencies: started
  Installing build dependencies: finished with status 'error'
  error: subprocess-exited-with-error
  
  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [4 lines of output]
      Collecting cython>=3.0.0
        Downloading Cython-3.0.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.2 kB)
      ERROR: Could not find a version that satisfies the requirement libucx==1.15.0 (from versions: none)
      ERROR: No matching distribution found for libucx==1.15.0
      [end of output]

(build link)

I just added PIP_NO_BUILD_ISOLATION="True" to the environment as well... still didn't work 😞

(build link)

I have one other idea, will post in a second.

Copy link
Member Author

Choose a reason for hiding this comment

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

To summarize.... these things did not work:

  • set env variable PIP_NO_DEPS="True" in readthedocs builds
  • set env variable PIP_NO_BUILD_ISOLATION="True" in readthedocs builds
  • set both of the above in readthedocs builds
  • set any combination of those environment variables in variables: block in builddocs.yml conda env
  • pass pip: - --no-deps ../../ via builddocs.yml conda env
  • use a real, suffixed dependency name like libucx-cu11>=1.15.0 in pyproject.toml + add --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple in builddocs.yml conda env

That last one failing revealed a more significant issue, not limited to just docs building...

calling libucx.load_library() unconditionally means ucx-py will not be importable unless the process has access to a GPU 😱

RuntimeError: The CUDA driver library libcuda.so.1 was not found on your system. This library cannot be provided by the libucx wheel and must be installed separately.

(build link)

The docs DO BUILD successfully on the current state of this branch 🎉 (build link), but only because I added behavior to work around not having a GPU available.

So @pentschev @vyasr that's a design decision for you.

When someone tries to import ucp without access to a GPU, what should happen?

  • the import should fail
  • the import should warn but succeed
  • something else

Copy link
Member Author

@jameslamb jameslamb May 10, 2024

Choose a reason for hiding this comment

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

Summarizing our offline conversations:

  • yes ucx-py is expected to be usable without a GPU
  • the libucx wheels should stop raising exceptions when libucx.load_library() is called in an environment without a GPU

In response, we published a new libucx==1.15.0.post1 removing those exceptions: rapidsai/ucx-wheels#5

Tested it with ucxx on systems with and without a GPU, and it seemed to work well: rapidsai/ucx-wheels#5 (comment)

Those new wheels helped the docs builds here get further, but those builds exposed another issue... as of the changes in this PR, ucx-py was compiling with the system-installed headers (e.g. /usr/include/ucm) but the wheel-provided shared libraries (e.g. site-packages/libucx/lib/libucm.so.0).

That showed up in "symbol not found" issues like this:

OSError: ${HOME}/conda/1041/lib/python3.12/site-packages/libucx/lib/libucs_signal.so: undefined symbol: ucs_debug_is_error_signal

(build link)

I just pushed a change that fixes that: eba110f

And looks like the docs builds are happy and docs are rendering correctly (RTD build link) 🎉

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch on the headers! I forgot to check on those. Glad you found this issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

Update for those finding this thread from search or other links.... thanks to @bdice 's suggestion in #1044 (comment), we were able to get this working without messing with environment variables or the conda environment YAML file, like this in .readthedocs.yaml:

    post_create_environment:
      - |
        pip install \
          --extra-index-url "https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/" \
          -C rapidsai.disable-cuda=true \
          -C rapidsai.matrix-entry="cuda=12.2" \
          .


conda:
environment: conda/environments/builddocs.yml
Expand Down
17 changes: 17 additions & 0 deletions ci/build_docs_pre_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# Copyright (c) 2024 NVIDIA CORPORATION.
#
# [description]
#
# ucx-py's docs builds require installing the library.
#
# It does that by running 'pip install .' from the root of the repo. This script
# is used to modify readthedocs' local checkout of this project's source code prior
# to that 'pip install' being run.
#
# For more, see https://docs.readthedocs.io/en/stable/build-customization.html
#

set -euo pipefail

sed -r -i "s/\"libucx/\"libucx-cu12/g" ./pyproject.toml
105 changes: 22 additions & 83 deletions ci/build_wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ set -euo pipefail
package_name="ucx-py"
underscore_package_name=$(echo "${package_name}" | tr "-" "_")

# Clear out system ucx files to ensure that we're getting ucx from the wheel.
rm -rf /usr/lib64/ucx
rm -rf /usr/lib64/libucm.*
rm -rf /usr/lib64/libucp.*
rm -rf /usr/lib64/libucs.*
rm -rf /usr/lib64/libucs_signal.*
rm -rf /usr/lib64/libuct.*

rm -rf /usr/include/ucm
rm -rf /usr/include/ucp
rm -rf /usr/include/ucs
rm -rf /usr/include/uct

source rapids-configure-sccache
source rapids-date-string

Expand Down Expand Up @@ -35,96 +48,22 @@ if ! rapids-is-release-build; then
fi

sed -r -i "s/cudf==(.*)\"/cudf${PACKAGE_CUDA_SUFFIX}==\1${alpha_spec}\"/g" ${pyproject_file}
sed -r -i "/\"libucx([=><]+)/ s/\"libucx/\"libucx${PACKAGE_CUDA_SUFFIX}/g" ${pyproject_file}

if [[ $PACKAGE_CUDA_SUFFIX == "-cu12" ]]; then
sed -i "s/cupy-cuda11x/cupy-cuda12x/g" ${pyproject_file}
fi


python -m pip wheel . -w dist -vvv --no-deps --disable-pip-version-check

mkdir -p final_dist
python -m auditwheel repair -w final_dist dist/*

# Auditwheel rewrites dynamic libraries that are referenced at link time in the
# package. However, UCX loads a number of sub-libraries at runtime via dlopen;
# these are not picked up by auditwheel. Since we have a priori knowledge of
# what these libraries are, we mimic the behaviour of auditwheel by using the
# same hash-based uniqueness scheme and rewriting the link paths.

WHL=$(realpath final_dist/${underscore_package_name}*manylinux*.whl)

# first grab the auditwheel hashes for libuc{tms}
LIBUCM=$(unzip -l $WHL | awk 'match($4, /libucm-[^\.]+\./) { print substr($4, RSTART) }')
LIBUCT=$(unzip -l $WHL | awk 'match($4, /libuct-[^\.]+\./) { print substr($4, RSTART) }')
LIBUCS=$(unzip -l $WHL | awk 'match($4, /libucs-[^\.]+\./) { print substr($4, RSTART) }')

# Extract the libraries that have already been patched in by auditwheel
mkdir -p repair_dist/${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.libs/ucx
unzip $WHL "${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.libs/*.so*" -d repair_dist/

# Patch the RPATH to include ORIGIN for each library
pushd repair_dist/${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.libs
for f in libu*.so*
do
if [[ -f $f ]]; then
patchelf --add-rpath '$ORIGIN' $f
fi
done

popd

# Now copy in all the extra libraries that are only ever loaded at runtime
pushd repair_dist/${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.libs/ucx
if [[ -d /usr/lib64/ucx ]]; then
cp -P /usr/lib64/ucx/* .
elif [[ -d /usr/lib/ucx ]]; then
cp -P /usr/lib/ucx/* .
else
echo "Could not find ucx libraries"
exit 1
fi

# we link against <python>/lib/site-packages/${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.lib/libuc{ptsm}
# we also amend the rpath to search one directory above to *find* libuc{tsm}
for f in libu*.so*
do
# Avoid patching symlinks, which is redundant
if [[ ! -L $f ]]; then
patchelf --replace-needed libuct.so.0 $LIBUCT $f
patchelf --replace-needed libucs.so.0 $LIBUCS $f
patchelf --replace-needed libucm.so.0 $LIBUCM $f
patchelf --add-rpath '$ORIGIN/..' $f
fi
done

# Bring in cudart as well. To avoid symbol collision with other libraries e.g.
# cupy we mimic auditwheel by renaming the libraries to include the hashes of
# their names. Since there will typically be a chain of symlinks
# libcudart.so->libcudart.so.X->libcudart.so.X.Y.Z we need to follow the chain
# and rename all of them.

find /usr/local/cuda/ -name "libcudart*.so*" | xargs cp -P -t .
src=libcudart.so
hash=$(sha256sum ${src} | awk '{print substr($1, 0, 8)}')
target=$(basename $(readlink -f ${src}))

mv ${target} ${target/libcudart/libcudart-${hash}}
while readlink ${src} > /dev/null; do
target=$(readlink ${src})
ln -s ${target/libcudart/libcudart-${hash}} ${src/libcudart/libcudart-${hash}}
rm -f ${src}
src=${target}
done

to_rewrite=$(ldd libuct_cuda.so | awk '/libcudart/ { print $1 }')
patchelf --replace-needed ${to_rewrite} libcudart-${hash}.so libuct_cuda.so
patchelf --add-rpath '$ORIGIN' libuct_cuda.so

popd

pushd repair_dist
zip -r $WHL ${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}.libs/
popd
python -m auditwheel repair \
-w final_dist \
--exclude "libucm.so.0" \
--exclude "libucp.so.0" \
--exclude "libucs.so.0" \
--exclude "libucs_signal.so.0" \
--exclude "libuct.so.0" \
dist/*

RAPIDS_PY_WHEEL_NAME="${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}" rapids-upload-wheels-to-s3 final_dist
4 changes: 3 additions & 1 deletion conda/environments/builddocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ dependencies:
- recommonmark
- pandoc=<2.0.0
- pip
- ucx
- pip:
- --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple
- ../../
- cython
6 changes: 4 additions & 2 deletions conda/recipes/ucx-py/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ requirements:
- python
- pip
- ucx
{% for r in data.get("build-system", {}).get("requires", []) %}
# 'libucx' wheel dependency is unnecessary... the 'ucx' conda-forge package is used here instead
{% for r in data.get("build-system", {}).get("requires", []) if not r.startswith("libucx") %}
- {{ r }}
{% endfor %}
run:
- python
- ucx >=1.15.0,<1.16.0
{% for r in data.get("project", {}).get("dependencies", []) %}
# 'libucx' wheel dependency is unnecessary... the 'ucx' conda-forge package is used here instead
{% for r in data.get("project", {}).get("dependencies", []) if not r.startswith("libucx") %}
- {{ r }}
{% endfor %}

Expand Down
47 changes: 47 additions & 0 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ files:
table: build-system
includes:
- build_python
- depends_on_ucx_build
py_run:
output: pyproject
pyproject_dir: .
extras:
table: project
includes:
- run
- depends_on_ucx_run
py_optional_test:
output: pyproject
pyproject_dir: .
Expand Down Expand Up @@ -115,9 +117,54 @@ dependencies:
packages:
- numpy>=1.23,<2.0a0
- pynvml>=11.4.1
depends_on_ucx_build:
common:
- output_types: conda
packages:
- ucx==1.15.0
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
- --extra-index-url=https://pypi.nvidia.com
- --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple
specific:
- output_types: [requirements, pyproject]
matrices:
- matrix: {cuda: "12.*"}
packages:
- libucx-cu12==1.15.0
- matrix: {cuda: "11.*"}
packages:
- libucx-cu11==1.15.0
# NOTE: this fallback needs to be a real, suffixed version
# so 'pip install .' (e.g. as used in docs builds) will work
- matrix: null
packages:
- libucx==1.15.0
depends_on_ucx_run:
common:
- output_types: conda
packages:
- ucx>=1.15.0,<1.16
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
- --extra-index-url=https://pypi.nvidia.com
- --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple
specific:
- output_types: [requirements, pyproject]
matrices:
- matrix: {cuda: "12.*"}
packages:
- libucx-cu12>=1.15.0,<1.16
- matrix: {cuda: "11.*"}
packages:
- libucx-cu11>=1.15.0,<1.16
# NOTE: this fallback needs to be a real, suffixed version
# so "pip install ." (e.g. as used in docs builds) will work
- matrix: null
packages:
- libucx>=1.15.0,<1.16
test_python:
common:
- output_types: [conda, requirements, pyproject]
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
build-backend = "setuptools.build_meta"
requires = [
"cython>=3.0.0",
"libucx==1.15.0",
jameslamb marked this conversation as resolved.
Show resolved Hide resolved
"setuptools>=64.0.0",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit dependencies.yaml and run `rapids-dependency-file-generator`.

Expand All @@ -30,6 +31,7 @@ authors = [
license = { text = "BSD-3-Clause" }
requires-python = ">=3.9"
dependencies = [
"libucx>=1.15.0,<1.16",
"numpy>=1.23,<2.0a0",
"pynvml>=11.4.1",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit dependencies.yaml and run `rapids-dependency-file-generator`.
Expand Down
49 changes: 49 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,67 @@

from __future__ import absolute_import, print_function

import glob
import os
from distutils.sysconfig import get_config_var, get_python_inc

from Cython.Distutils.build_ext import new_build_ext
from setuptools import setup
from setuptools.extension import Extension


def _find_libucx_libs_and_headers():
vyasr marked this conversation as resolved.
Show resolved Hide resolved
"""
If the 'libucx' wheel is not installed, returns a tuple of empty lists.
In that case, the project will be compiled against system installations
of the UCX libraries.

If 'libucx' is installed, returns lists of library and header paths to help
the compiler and linker find its contents. In that case, the project will
be compiled against those libucx-wheel-provided versions of the UCX libraries.
"""
try:
import libucx
except ImportError:
return [], []

# find 'libucx'
module_dir = os.path.dirname(libucx.__file__)

# find where it stores files like 'libucm.so.0'
libs = glob.glob(f"{module_dir}/**/lib*.so*", recursive=True)

# deduplicate those library paths
lib_dirs = {os.path.dirname(f) for f in libs}
if not lib_dirs:
raise RuntimeError(
f"Did not find shared libraries in 'libucx' install location ({module_dir})"
)

# find where it stores headers
headers = glob.glob(f"{module_dir}/**/include", recursive=True)

# deduplicate those header paths (and ensure the list only includes directories)
header_dirs = {f for f in headers if os.path.isdir(f)}
if not header_dirs:
raise RuntimeError(
f"Did not find UCX headers 'libucx' install location ({module_dir})"
)

return list(lib_dirs), list(header_dirs)


include_dirs = [os.path.dirname(get_python_inc())]
library_dirs = [get_config_var("LIBDIR")]
libraries = ["ucp", "uct", "ucm", "ucs"]
extra_compile_args = ["-std=c99", "-Werror"]

# tell the compiler and linker where to find UCX libraries and their headers
# provided by the 'libucx' wheel
libucx_lib_dirs, libucx_header_dirs = _find_libucx_libs_and_headers()
library_dirs.extend(libucx_lib_dirs)
include_dirs.extend(libucx_header_dirs)


ext_modules = [
Extension(
Expand Down
12 changes: 12 additions & 0 deletions ucp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@
logger.debug("Setting env UCX_MEMTYPE_CACHE=n, which is required by UCX")
os.environ["UCX_MEMTYPE_CACHE"] = "n"


# If libucx was installed as a wheel, we must request it to load the library symbols.
# Otherwise, we assume that the library was installed in a system path that ld can find.
try:
import libucx
except ImportError:
pass
else:
libucx.load_library()
del libucx
vyasr marked this conversation as resolved.
Show resolved Hide resolved


from .core import * # noqa
from .core import get_ucx_version # noqa
from .utils import get_ucxpy_logger # noqa
Expand Down