diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5f80d8cfda..d484bcae22 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -66,7 +66,30 @@ jobs: node_type: "gpu-v100-latest-1" run_script: "ci/build_docs.sh" sha: ${{ inputs.sha }} + wheel-build-libraft: + secrets: inherit + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 + with: + build_type: ${{ inputs.build_type || 'branch' }} + branch: ${{ inputs.branch }} + sha: ${{ inputs.sha }} + date: ${{ inputs.date }} + script: ci/build_wheel_libraft.sh + # build for every combination of arch and CUDA version, but only for the latest Python + matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber))) + wheel-publish-libraft: + needs: wheel-build-libraft + secrets: inherit + uses: rapidsai/shared-workflows/.github/workflows/wheels-publish.yaml@branch-25.02 + with: + build_type: ${{ inputs.build_type || 'branch' }} + branch: ${{ inputs.branch }} + sha: ${{ inputs.sha }} + date: ${{ inputs.date }} + package-name: libraft + package-type: cpp wheel-build-pylibraft: + needs: wheel-build-libraft secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 with: @@ -85,7 +108,9 @@ jobs: sha: ${{ inputs.sha }} date: ${{ inputs.date }} package-name: pylibraft + package-type: python wheel-build-raft-dask: + needs: wheel-build-libraft secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 with: @@ -104,3 +129,4 @@ jobs: sha: ${{ inputs.sha }} date: ${{ inputs.date }} package-name: raft_dask + package-type: python diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index a270df1dfa..9a51c783e9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -21,6 +21,7 @@ jobs: - conda-python-build - conda-python-tests - docs-build + - wheel-build-libraft - wheel-build-pylibraft - wheel-tests-pylibraft - wheel-build-raft-dask @@ -116,10 +117,22 @@ jobs: arch: "amd64" container_image: "rapidsai/ci-conda:latest" run_script: "ci/build_docs.sh" - wheel-build-pylibraft: + wheel-build-libraft: needs: checks secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 + with: + build_type: pull-request + branch: ${{ inputs.branch }} + sha: ${{ inputs.sha }} + date: ${{ inputs.date }} + script: ci/build_wheel_libraft.sh + # build for every combination of arch and CUDA version, but only for the latest Python + matrix_filter: group_by([.ARCH, (.CUDA_VER|split(".")|map(tonumber)|.[0])]) | map(max_by(.PY_VER|split(".")|map(tonumber))) + wheel-build-pylibraft: + needs: [checks, wheel-build-libraft] + secrets: inherit + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 with: build_type: pull-request script: ci/build_wheel_pylibraft.sh @@ -132,7 +145,7 @@ jobs: build_type: pull-request script: ci/test_wheel_pylibraft.sh wheel-build-raft-dask: - needs: wheel-tests-pylibraft + needs: [checks, wheel-build-libraft] secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@branch-25.02 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d5456ba30b..ca1efc3abd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -83,7 +83,7 @@ repos: exclude: .*/thirdparty/.* - id: include-check name: include-check - entry: python ./cpp/scripts/include_checker.py cpp/bench cpp/include cpp/test + entry: python ./cpp/scripts/include_checker.py cpp/bench cpp/include cpp/tests pass_filenames: false language: python additional_dependencies: [gitpython] diff --git a/build.sh b/build.sh index a95cb8ee23..de3ebfa3c5 100755 --- a/build.sh +++ b/build.sh @@ -347,13 +347,8 @@ if [[ ${CMAKE_TARGET} == "" ]]; then CMAKE_TARGET="all" fi -# Append `-DFIND_RAFT_CPP=ON` to EXTRA_CMAKE_ARGS unless a user specified the option. -SKBUILD_EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS}" -if [[ "${EXTRA_CMAKE_ARGS}" != *"DFIND_RAFT_CPP"* ]]; then - SKBUILD_EXTRA_CMAKE_ARGS="${SKBUILD_EXTRA_CMAKE_ARGS} -DFIND_RAFT_CPP=ON" -fi # Replace spaces with semicolons in SKBUILD_EXTRA_CMAKE_ARGS -SKBUILD_EXTRA_CMAKE_ARGS=$(echo ${SKBUILD_EXTRA_CMAKE_ARGS} | sed 's/ /;/g') +SKBUILD_EXTRA_CMAKE_ARGS=$(echo ${EXTRA_CMAKE_ARGS} | sed 's/ /;/g') # If clean given, run it prior to any other steps if (( ${CLEAN} == 1 )); then diff --git a/ci/build_wheel.sh b/ci/build_wheel.sh index 326ee9a4c7..976da98998 100755 --- a/ci/build_wheel.sh +++ b/ci/build_wheel.sh @@ -5,6 +5,7 @@ set -euo pipefail package_name=$1 package_dir=$2 +package_type=$3 underscore_package_name=$(echo "${package_name}" | tr "-" "_") # Clear out system ucx files to ensure that we're getting ucx from the wheel. @@ -20,24 +21,21 @@ rapids-generate-version > ./VERSION cd "${package_dir}" -case "${RAPIDS_CUDA_VERSION}" in - 12.*) - EXCLUDE_ARGS=( - --exclude "libcublas.so.12" - --exclude "libcublasLt.so.12" - --exclude "libcurand.so.10" - --exclude "libcusolver.so.11" - --exclude "libcusparse.so.12" - --exclude "libnvJitLink.so.12" - --exclude "libucp.so.0" +EXCLUDE_ARGS=( + --exclude "libcublas.so.*" + --exclude "libcublasLt.so.*" + --exclude "libcurand.so.*" + --exclude "libcusolver.so.*" + --exclude "libcusparse.so.*" + --exclude "libnvJitLink.so.*" + --exclude "libucp.so.*" +) + +if [[ ${package_name} != "libraft" ]]; then + EXCLUDE_ARGS+=( + --exclude "libraft.so" ) - ;; - 11.*) - EXCLUDE_ARGS=( - --exclude "libucp.so.0" - ) - ;; -esac +fi sccache --zero-stats @@ -55,4 +53,4 @@ sccache --show-adv-stats mkdir -p final_dist python -m auditwheel repair -w final_dist "${EXCLUDE_ARGS[@]}" dist/* -RAPIDS_PY_WHEEL_NAME="${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}" rapids-upload-wheels-to-s3 python final_dist +RAPIDS_PY_WHEEL_NAME="${underscore_package_name}_${RAPIDS_PY_CUDA_SUFFIX}" rapids-upload-wheels-to-s3 ${package_type} final_dist diff --git a/ci/build_wheel_libraft.sh b/ci/build_wheel_libraft.sh new file mode 100755 index 0000000000..8ff0da1e9a --- /dev/null +++ b/ci/build_wheel_libraft.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2024, NVIDIA CORPORATION. + +set -euo pipefail + +package_name="libraft" +package_dir="python/libraft" + +rapids-logger "Generating build requirements" +matrix_selectors="cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION};cuda_suffixed=true" + +rapids-dependency-file-generator \ + --output requirements \ + --file-key "py_build_${package_name}" \ + --file-key "py_rapids_build_${package_name}" \ + --matrix "${matrix_selectors}" \ +| tee /tmp/requirements-build.txt + +rapids-logger "Installing build requirements" +python -m pip install \ + -v \ + --prefer-binary \ + -r /tmp/requirements-build.txt + +# build with '--no-build-isolation', for better sccache hit rate +# 0 really means "add --no-build-isolation" (ref: https://github.com/pypa/pip/issues/5735) +export PIP_NO_BUILD_ISOLATION=0 + +RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" + +ci/build_wheel.sh libraft ${package_dir} cpp +ci/validate_wheel.sh ${package_dir} final_dist libraft diff --git a/ci/build_wheel_pylibraft.sh b/ci/build_wheel_pylibraft.sh index dd62ab5399..6f74e0e8c5 100755 --- a/ci/build_wheel_pylibraft.sh +++ b/ci/build_wheel_pylibraft.sh @@ -5,17 +5,16 @@ set -euo pipefail package_dir="python/pylibraft" -case "${RAPIDS_CUDA_VERSION}" in - 12.*) - EXTRA_CMAKE_ARGS=";-DUSE_CUDA_MATH_WHEELS=ON" - ;; - 11.*) - EXTRA_CMAKE_ARGS=";-DUSE_CUDA_MATH_WHEELS=OFF" - ;; -esac +RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" -# Set up skbuild options. Enable sccache in skbuild config options -export SKBUILD_CMAKE_ARGS="-DDETECT_CONDA_ENV=OFF;-DFIND_RAFT_CPP=OFF${EXTRA_CMAKE_ARGS}" +# Downloads libraft wheels from this current build, +# then ensures 'pylibraft' wheel builds always use the 'libraft' just built in the same CI run. +# +# Using env variable PIP_CONSTRAINT is necessary to ensure the constraints +# are used when creating the isolated build environment. +RAPIDS_PY_WHEEL_NAME="libraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 cpp /tmp/libraft_dist +echo "libraft-${RAPIDS_PY_CUDA_SUFFIX} @ file://$(echo /tmp/libraft_dist/libraft_*.whl)" > /tmp/constraints.txt +export PIP_CONSTRAINT="/tmp/constraints.txt" -ci/build_wheel.sh pylibraft ${package_dir} +ci/build_wheel.sh pylibraft ${package_dir} python ci/validate_wheel.sh ${package_dir} final_dist pylibraft diff --git a/ci/build_wheel_raft_dask.sh b/ci/build_wheel_raft_dask.sh index d49d131abf..0cacb6fe30 100755 --- a/ci/build_wheel_raft_dask.sh +++ b/ci/build_wheel_raft_dask.sh @@ -5,8 +5,16 @@ set -euo pipefail package_dir="python/raft-dask" -# Set up skbuild options. Enable sccache in skbuild config options -export SKBUILD_CMAKE_ARGS="-DDETECT_CONDA_ENV=OFF;-DFIND_RAFT_CPP=OFF" +RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" -ci/build_wheel.sh raft-dask ${package_dir} +# Downloads libraft wheels from this current build, +# then ensures 'raft-dask' wheel builds always use the 'libraft' just built in the same CI run. +# +# Using env variable PIP_CONSTRAINT is necessary to ensure the constraints +# are used when creating the isolated build environment. +RAPIDS_PY_WHEEL_NAME="libraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 cpp /tmp/libraft_dist +echo "libraft-${RAPIDS_PY_CUDA_SUFFIX} @ file://$(echo /tmp/libraft_dist/libraft_*.whl)" > /tmp/constraints.txt +export PIP_CONSTRAINT="/tmp/constraints.txt" + +ci/build_wheel.sh raft-dask ${package_dir} python ci/validate_wheel.sh ${package_dir} final_dist raft-dask diff --git a/ci/check_style.sh b/ci/check_style.sh index d7ba4cae25..e0c30a2d41 100755 --- a/ci/check_style.sh +++ b/ci/check_style.sh @@ -14,5 +14,12 @@ rapids-dependency-file-generator \ rapids-mamba-retry env create --yes -f env.yaml -n checks conda activate checks +# get config for cmake-format checks +RAPIDS_VERSION_MAJOR_MINOR="$(rapids-version-major-minor)" +FORMAT_FILE_URL="https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-${RAPIDS_VERSION_MAJOR_MINOR}/cmake-format-rapids-cmake.json" +export RAPIDS_CMAKE_FORMAT_FILE=/tmp/rapids_cmake_ci/cmake-formats-rapids-cmake.json +mkdir -p $(dirname ${RAPIDS_CMAKE_FORMAT_FILE}) +wget -O ${RAPIDS_CMAKE_FORMAT_FILE} ${FORMAT_FILE_URL} + # Run pre-commit checks pre-commit run --all-files --show-diff-on-failure diff --git a/ci/release/update-version.sh b/ci/release/update-version.sh index a70fed9ec8..1ab9157b89 100755 --- a/ci/release/update-version.sh +++ b/ci/release/update-version.sh @@ -43,6 +43,8 @@ echo "${NEXT_FULL_TAG}" > VERSION DEPENDENCIES=( dask-cuda + libraft + librmm pylibraft rmm rapids-dask-dependency diff --git a/ci/run_pylibraft_pytests.sh b/ci/run_pylibraft_pytests.sh index 1167b89c5f..7f3d1f9cfb 100755 --- a/ci/run_pylibraft_pytests.sh +++ b/ci/run_pylibraft_pytests.sh @@ -6,4 +6,4 @@ set -euo pipefail # Support invoking run_pylibraft_pytests.sh outside the script directory cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../python/pylibraft/pylibraft -pytest --cache-clear "$@" test +pytest --cache-clear "$@" tests diff --git a/ci/run_raft_dask_pytests.sh b/ci/run_raft_dask_pytests.sh index 07d0b5baa0..a9e6a130cd 100755 --- a/ci/run_raft_dask_pytests.sh +++ b/ci/run_raft_dask_pytests.sh @@ -6,4 +6,4 @@ set -euo pipefail # Support invoking run_raft_dask_pytests.sh outside the script directory cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../python/raft-dask/raft_dask -pytest --cache-clear --import-mode=append "$@" test +pytest --cache-clear --import-mode=append "$@" tests diff --git a/ci/test_wheel_pylibraft.sh b/ci/test_wheel_pylibraft.sh index b38f5a690b..26f4da267f 100755 --- a/ci/test_wheel_pylibraft.sh +++ b/ci/test_wheel_pylibraft.sh @@ -5,9 +5,13 @@ set -euo pipefail mkdir -p ./dist RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" -RAPIDS_PY_WHEEL_NAME="pylibraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 ./dist +RAPIDS_PY_WHEEL_NAME="libraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 cpp ./local-libraft-dep +RAPIDS_PY_WHEEL_NAME="pylibraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 python ./dist + # echo to expand wildcard before adding `[extra]` requires for pip -python -m pip install $(echo ./dist/pylibraft*.whl)[test] +python -m pip install \ + ./local-libraft-dep/libraft*.whl \ + "$(echo ./dist/pylibraft*.whl)[test]" -python -m pytest ./python/pylibraft/pylibraft/test +python -m pytest ./python/pylibraft/pylibraft/tests diff --git a/ci/test_wheel_raft_dask.sh b/ci/test_wheel_raft_dask.sh index a778a3ec51..c394314aac 100755 --- a/ci/test_wheel_raft_dask.sh +++ b/ci/test_wheel_raft_dask.sh @@ -5,17 +5,17 @@ set -euo pipefail mkdir -p ./dist RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" -RAPIDS_PY_WHEEL_NAME="raft_dask_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 ./dist - -# Download the pylibraft built in the previous step -RAPIDS_PY_WHEEL_NAME="pylibraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 ./local-pylibraft-dep +RAPIDS_PY_WHEEL_NAME="libraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 cpp ./local-libraft-dep +RAPIDS_PY_WHEEL_NAME="pylibraft_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 python ./local-pylibraft-dep +RAPIDS_PY_WHEEL_NAME="raft_dask_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-s3 python ./dist # echo to expand wildcard before adding `[extra]` requires for pip python -m pip install -v \ + ./local-libraft-dep/libraft*.whl \ ./local-pylibraft-dep/pylibraft*.whl \ "$(echo ./dist/raft_dask_${RAPIDS_PY_CUDA_SUFFIX}*.whl)[test]" -test_dir="python/raft-dask/raft_dask/test" +test_dir="python/raft-dask/raft_dask/tests" rapids-logger "pytest raft-dask" python -m pytest --import-mode=append ${test_dir} diff --git a/ci/validate_wheel.sh b/ci/validate_wheel.sh index 5ef72ad895..ec3867aa30 100755 --- a/ci/validate_wheel.sh +++ b/ci/validate_wheel.sh @@ -9,33 +9,12 @@ package_name=$3 RAPIDS_CUDA_MAJOR="${RAPIDS_CUDA_VERSION%%.*}" -# some packages are much larger on CUDA 11 than on CUDA 12 -if [[ "${package_name}" == "raft-dask" ]]; then - PYDISTCHECK_ARGS=( - --max-allowed-size-compressed '200M' - ) -elif [[ "${package_name}" == "pylibraft" ]]; then - if [[ "${RAPIDS_CUDA_MAJOR}" == "11" ]]; then - PYDISTCHECK_ARGS=( - --max-allowed-size-compressed '600M' - ) - else - PYDISTCHECK_ARGS=( - --max-allowed-size-compressed '100M' - ) - fi -else - echo "Unsupported package name: ${package_name}" - exit 1 -fi - cd "${package_dir}" rapids-logger "validate packages with 'pydistcheck'" pydistcheck \ --inspect \ - "${PYDISTCHECK_ARGS[@]}" \ "$(echo ${wheel_dir_relative_path}/*.whl)" rapids-logger "validate packages with 'twine'" diff --git a/conda/environments/all_cuda-118_arch-aarch64.yaml b/conda/environments/all_cuda-118_arch-aarch64.yaml index 793ca8dc67..ecd9aa1ece 100644 --- a/conda/environments/all_cuda-118_arch-aarch64.yaml +++ b/conda/environments/all_cuda-118_arch-aarch64.yaml @@ -55,6 +55,6 @@ dependencies: - spdlog>=1.14.1,<1.15 - sphinx-copybutton - sphinx-markdown-tables -- sysroot_linux-aarch64==2.17 +- sysroot_linux-aarch64==2.28 - ucx-py==0.42.*,>=0.0.0a0 name: all_cuda-118_arch-aarch64 diff --git a/conda/environments/all_cuda-118_arch-x86_64.yaml b/conda/environments/all_cuda-118_arch-x86_64.yaml index a9f839bd03..2f655ae077 100644 --- a/conda/environments/all_cuda-118_arch-x86_64.yaml +++ b/conda/environments/all_cuda-118_arch-x86_64.yaml @@ -55,6 +55,6 @@ dependencies: - spdlog>=1.14.1,<1.15 - sphinx-copybutton - sphinx-markdown-tables -- sysroot_linux-64==2.17 +- sysroot_linux-64==2.28 - ucx-py==0.42.*,>=0.0.0a0 name: all_cuda-118_arch-x86_64 diff --git a/conda/environments/all_cuda-125_arch-aarch64.yaml b/conda/environments/all_cuda-125_arch-aarch64.yaml index 9d7286bb8e..d790e985fa 100644 --- a/conda/environments/all_cuda-125_arch-aarch64.yaml +++ b/conda/environments/all_cuda-125_arch-aarch64.yaml @@ -24,7 +24,7 @@ dependencies: - dask-cuda==25.2.*,>=0.0.0a0 - distributed-ucxx==0.42.*,>=0.0.0a0 - doxygen>=1.8.20 -- gcc_linux-aarch64=11.* +- gcc_linux-aarch64=13.* - graphviz - ipython - libcublas-dev @@ -51,6 +51,6 @@ dependencies: - spdlog>=1.14.1,<1.15 - sphinx-copybutton - sphinx-markdown-tables -- sysroot_linux-aarch64==2.17 +- sysroot_linux-aarch64==2.28 - ucx-py==0.42.*,>=0.0.0a0 name: all_cuda-125_arch-aarch64 diff --git a/conda/environments/all_cuda-125_arch-x86_64.yaml b/conda/environments/all_cuda-125_arch-x86_64.yaml index e4ec074ae5..63808d99c0 100644 --- a/conda/environments/all_cuda-125_arch-x86_64.yaml +++ b/conda/environments/all_cuda-125_arch-x86_64.yaml @@ -24,7 +24,7 @@ dependencies: - dask-cuda==25.2.*,>=0.0.0a0 - distributed-ucxx==0.42.*,>=0.0.0a0 - doxygen>=1.8.20 -- gcc_linux-64=11.* +- gcc_linux-64=13.* - graphviz - ipython - libcublas-dev @@ -51,6 +51,6 @@ dependencies: - spdlog>=1.14.1,<1.15 - sphinx-copybutton - sphinx-markdown-tables -- sysroot_linux-64==2.17 +- sysroot_linux-64==2.28 - ucx-py==0.42.*,>=0.0.0a0 name: all_cuda-125_arch-x86_64 diff --git a/conda/recipes/libraft/conda_build_config.yaml b/conda/recipes/libraft/conda_build_config.yaml index 4857f12cd1..11b16bc2a8 100644 --- a/conda/recipes/libraft/conda_build_config.yaml +++ b/conda/recipes/libraft/conda_build_config.yaml @@ -1,20 +1,20 @@ c_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cxx_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cuda_compiler: - - cuda-nvcc - -cuda11_compiler: - - nvcc + - cuda-nvcc # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - nvcc # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] c_stdlib: - sysroot c_stdlib_version: - - "2.17" + - "2.28" cmake_version: - ">=3.26.4,!=3.30.0" diff --git a/conda/recipes/libraft/meta.yaml b/conda/recipes/libraft/meta.yaml index 503c4cb6fb..dbde4e3971 100644 --- a/conda/recipes/libraft/meta.yaml +++ b/conda/recipes/libraft/meta.yaml @@ -39,10 +39,8 @@ outputs: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev {% endif %} - librmm @@ -51,7 +49,7 @@ outputs: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} @@ -85,11 +83,7 @@ outputs: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} - {% endif %} - librmm requirements: host: @@ -130,10 +124,8 @@ outputs: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev - libcublas-dev - libcurand-dev @@ -145,7 +137,7 @@ outputs: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} @@ -196,10 +188,8 @@ outputs: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev {% endif %} requirements: @@ -207,7 +197,7 @@ outputs: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} @@ -258,10 +248,8 @@ outputs: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev - libcublas-dev - libcurand-dev @@ -273,7 +261,7 @@ outputs: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} diff --git a/conda/recipes/pylibraft/conda_build_config.yaml b/conda/recipes/pylibraft/conda_build_config.yaml index 001878ff25..83f5ebcb15 100644 --- a/conda/recipes/pylibraft/conda_build_config.yaml +++ b/conda/recipes/pylibraft/conda_build_config.yaml @@ -1,20 +1,20 @@ c_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cxx_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cuda_compiler: - - cuda-nvcc - -cuda11_compiler: - - nvcc + - cuda-nvcc # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - nvcc # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] c_stdlib: - sysroot c_stdlib_version: - - "2.17" + - "2.28" cmake_version: - ">=3.26.4,!=3.30.0" diff --git a/conda/recipes/pylibraft/meta.yaml b/conda/recipes/pylibraft/meta.yaml index 0b57432402..8f498c7e50 100644 --- a/conda/recipes/pylibraft/meta.yaml +++ b/conda/recipes/pylibraft/meta.yaml @@ -18,10 +18,8 @@ build: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_py{{ py_version }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev {% endif %} - cuda-python @@ -31,7 +29,7 @@ requirements: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} diff --git a/conda/recipes/raft-dask/conda_build_config.yaml b/conda/recipes/raft-dask/conda_build_config.yaml index 68140e6bc0..d567266027 100644 --- a/conda/recipes/raft-dask/conda_build_config.yaml +++ b/conda/recipes/raft-dask/conda_build_config.yaml @@ -1,20 +1,20 @@ c_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cxx_compiler_version: - - 11 + - 13 # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - 11 # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] cuda_compiler: - - cuda-nvcc - -cuda11_compiler: - - nvcc + - cuda-nvcc # [not os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] + - nvcc # [os.environ.get("RAPIDS_CUDA_VERSION", "").startswith("11")] c_stdlib: - sysroot c_stdlib_version: - - "2.17" + - "2.28" ucx_py_version: - "0.42.*" diff --git a/conda/recipes/raft-dask/meta.yaml b/conda/recipes/raft-dask/meta.yaml index 19155166af..29c7f568f1 100644 --- a/conda/recipes/raft-dask/meta.yaml +++ b/conda/recipes/raft-dask/meta.yaml @@ -18,10 +18,8 @@ build: number: {{ GIT_DESCRIBE_NUMBER }} string: cuda{{ cuda_major }}_py{{ py_version }}_{{ date_string }}_{{ GIT_DESCRIBE_HASH }}_{{ GIT_DESCRIBE_NUMBER }} ignore_run_exports_from: - {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} - {% else %} - {{ compiler('cuda') }} + {% if cuda_major != "11" %} - cuda-cudart-dev {% endif %} - cuda-python @@ -31,7 +29,7 @@ requirements: - {{ compiler('c') }} - {{ compiler('cxx') }} {% if cuda_major == "11" %} - - {{ compiler('cuda11') }} ={{ cuda_version }} + - {{ compiler('cuda') }} ={{ cuda_version }} {% else %} - {{ compiler('cuda') }} {% endif %} diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 621f9fcef2..c38471bebd 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -65,9 +65,12 @@ set(RAFT_COMPILE_LIBRARY_DEFAULT OFF) if(BUILD_TESTS OR BUILD_PRIMS_BENCH) set(RAFT_COMPILE_LIBRARY_DEFAULT ON) endif() -option(RAFT_COMPILE_LIBRARY "Enable building raft shared library instantiations" +option(RAFT_COMPILE_LIBRARY "Enable building raft library instantiations" ${RAFT_COMPILE_LIBRARY_DEFAULT} ) +option(RAFT_COMPILE_DYNAMIC_ONLY "Only build the shared library and skip the +static library. Has no effect if RAFT_COMPILE_LIBRARY is OFF" OFF +) # Needed because GoogleBenchmark changes the state of FindThreads.cmake, causing subsequent runs to # have different values for the `Threads::Threads` target. Setting this flag ensures @@ -311,17 +314,23 @@ if(RAFT_COMPILE_LIBRARY) # Make sure not to add the rmm logger twice since it will be brought in as an interface source by # the rmm::rmm_logger_impl target. add_library(raft_lib SHARED $,EXCLUDE,rmm.*logger>) - add_library(raft_lib_static STATIC $,EXCLUDE,rmm.*logger>) + + set(_raft_lib_targets raft_lib) + if(NOT RAFT_COMPILE_DYNAMIC_ONLY) + add_library(raft_lib_static STATIC $,EXCLUDE,rmm.*logger>) + list(APPEND _raft_lib_targets raft_lib_static) + endif() set_target_properties( - raft_lib raft_lib_static + ${_raft_lib_targets} PROPERTIES OUTPUT_NAME raft BUILD_RPATH "\$ORIGIN" INSTALL_RPATH "\$ORIGIN" INTERFACE_POSITION_INDEPENDENT_CODE ON ) - foreach(target raft_lib raft_lib_static raft_objs) + list(APPEND _raft_lib_targets raft_objs) + foreach(target IN LISTS _raft_lib_targets) target_link_libraries( ${target} PUBLIC raft::raft @@ -336,7 +345,9 @@ if(RAFT_COMPILE_LIBRARY) target_link_options(${target} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/fatbin.ld") endforeach() target_link_libraries(raft_lib PRIVATE rmm::rmm_logger_impl raft_logger_impl) - target_link_libraries(raft_lib_static PRIVATE rmm::rmm_logger_impl raft_logger_impl) + if(NOT RAFT_COMPILE_DYNAMIC_ONLY) + target_link_libraries(raft_lib_static PRIVATE rmm::rmm_logger_impl raft_logger_impl) + endif() endif() if(TARGET raft_lib AND (NOT TARGET raft::raft_lib)) @@ -348,20 +359,22 @@ target_link_libraries(raft_compiled INTERFACE raft::raft $ -) + target_link_libraries( + raft_compiled_static INTERFACE raft::raft $ + ) +endif() # ################################################################################################## # * raft_distributed ------------------------------------------------------------------------------- @@ -410,8 +423,12 @@ install( EXPORT raft-exports ) +set(_raft_compiled_install_targets raft_compiled) +if(NOT RAFT_COMPILE_DYNAMIC_ONLY) + list(APPEND _raft_compiled_install_targets raft_compiled_static) +endif() install( - TARGETS raft_compiled raft_compiled_static + TARGETS ${_raft_compiled_install_targets} DESTINATION ${lib_dir} COMPONENT raft EXPORT raft-compiled-exports @@ -424,12 +441,14 @@ if(TARGET raft_lib) COMPONENT compiled EXPORT raft-compiled-lib-exports ) - install( - TARGETS raft_lib_static - DESTINATION ${lib_dir} - COMPONENT compiled-static - EXPORT raft-compiled-static-lib-exports - ) + if(NOT RAFT_COMPILE_DYNAMIC_ONLY) + install( + TARGETS raft_lib_static + DESTINATION ${lib_dir} + COMPONENT compiled-static + EXPORT raft-compiled-static-lib-exports + ) + endif() install( DIRECTORY include/raft_runtime DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} @@ -500,8 +519,12 @@ endif() set(raft_components compiled distributed) set(raft_export_sets raft-compiled-exports raft-distributed-exports) if(TARGET raft_lib) - list(APPEND raft_components compiled compiled-static) - list(APPEND raft_export_sets raft-compiled-lib-exports raft-compiled-static-lib-exports) + list(APPEND raft_components compiled) + list(APPEND raft_export_sets raft-compiled-lib-exports) + if(NOT RAFT_COMPILE_DYNAMIC_ONLY) + list(APPEND raft_components compiled-static) + list(APPEND raft_export_sets raft-compiled-static-lib-exports) + endif() endif() string( @@ -563,7 +586,7 @@ endif() # * build test executable ---------------------------------------------------- if(BUILD_TESTS) - add_subdirectory(test) + add_subdirectory(tests) endif() # ################################################################################################## diff --git a/cpp/cmake/modules/ConfigureCUDA.cmake b/cpp/cmake/modules/ConfigureCUDA.cmake index b364d8418d..fbf4428650 100644 --- a/cpp/cmake/modules/ConfigureCUDA.cmake +++ b/cpp/cmake/modules/ConfigureCUDA.cmake @@ -1,5 +1,5 @@ # ============================================================================= -# Copyright (c) 2018-2024, NVIDIA CORPORATION. +# Copyright (c) 2018-2025, NVIDIA CORPORATION. # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at @@ -14,7 +14,9 @@ if(DISABLE_DEPRECATION_WARNINGS) list(APPEND RAFT_CXX_FLAGS -Wno-deprecated-declarations -DRAFT_HIDE_DEPRECATION_WARNINGS) - list(APPEND RAFT_CUDA_FLAGS -Xcompiler=-Wno-deprecated-declarations -DRAFT_HIDE_DEPRECATION_WARNINGS) + list(APPEND RAFT_CUDA_FLAGS -Xcompiler=-Wno-deprecated-declarations + -DRAFT_HIDE_DEPRECATION_WARNINGS + ) endif() # Be very strict when compiling with GCC as host compiler (and thus more lenient when compiling with @@ -27,6 +29,12 @@ if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2.0) list(APPEND RAFT_CUDA_FLAGS -Werror=all-warnings) endif() + + # Allow invalid CUDA kernels in the short term + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8.0) + list(APPEND RAFT_CUDA_FLAGS -static-global-template-stub=false) + endif() + endif() if(CUDA_LOG_COMPILE_TIME) diff --git a/cpp/include/raft/comms/nccl_clique.hpp b/cpp/include/raft/comms/nccl_clique.hpp new file mode 100644 index 0000000000..c6520af753 --- /dev/null +++ b/cpp/include/raft/comms/nccl_clique.hpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include + +/** + * @brief Error checking macro for NCCL runtime API functions. + * + * Invokes a NCCL runtime API function call, if the call does not return ncclSuccess, throws an + * exception detailing the NCCL error that occurred + */ +#define RAFT_NCCL_TRY(call) \ + do { \ + ncclResult_t const status = (call); \ + if (ncclSuccess != status) { \ + std::string msg{}; \ + SET_ERROR_MSG(msg, \ + "NCCL error encountered at: ", \ + "call='%s', Reason=%d:%s", \ + #call, \ + status, \ + ncclGetErrorString(status)); \ + throw raft::logic_error(msg); \ + } \ + } while (0); + +namespace raft::comms { +void build_comms_nccl_only(raft::resources* handle, ncclComm_t nccl_comm, int num_ranks, int rank); +} + +namespace raft::comms { + +struct nccl_clique { + using pool_mr = rmm::mr::pool_memory_resource; + + /** + * Instantiates a NCCL clique with all available GPUs + * + * @param[in] percent_of_free_memory percentage of device memory to pre-allocate as memory pool + * + */ + nccl_clique(int percent_of_free_memory = 80) + : root_rank_(0), + percent_of_free_memory_(percent_of_free_memory), + per_device_pools_(0), + device_resources_(0) + { + cudaGetDeviceCount(&num_ranks_); + device_ids_.resize(num_ranks_); + std::iota(device_ids_.begin(), device_ids_.end(), 0); + nccl_comms_.resize(num_ranks_); + nccl_clique_init(); + } + + /** + * Instantiates a NCCL clique + * + * Usage example: + * @code{.cpp} + * int n_devices; + * cudaGetDeviceCount(&n_devices); + * std::vector device_ids(n_devices); + * std::iota(device_ids.begin(), device_ids.end(), 0); + * cuvs::neighbors::mg::nccl_clique& clique(device_ids); // first device is the root rank + * @endcode + * + * @param[in] device_ids list of device IDs to be used to initiate the clique + * @param[in] percent_of_free_memory percentage of device memory to pre-allocate as memory pool + * + */ + nccl_clique(const std::vector& device_ids, int percent_of_free_memory = 80) + : root_rank_(0), + num_ranks_(device_ids.size()), + percent_of_free_memory_(percent_of_free_memory), + device_ids_(device_ids), + nccl_comms_(device_ids.size()), + per_device_pools_(0), + device_resources_(0) + { + nccl_clique_init(); + } + + void nccl_clique_init() + { + RAFT_NCCL_TRY(ncclCommInitAll(nccl_comms_.data(), num_ranks_, device_ids_.data())); + + for (int rank = 0; rank < num_ranks_; rank++) { + RAFT_CUDA_TRY(cudaSetDevice(device_ids_[rank])); + + // create a pool memory resource for each device + auto old_mr = rmm::mr::get_current_device_resource(); + per_device_pools_.push_back(std::make_unique( + old_mr, rmm::percent_of_free_device_memory(percent_of_free_memory_))); + rmm::cuda_device_id id(device_ids_[rank]); + rmm::mr::set_per_device_resource(id, per_device_pools_.back().get()); + + // create a device resource handle for each device + device_resources_.emplace_back(); + + // add NCCL communications to the device resource handle + raft::comms::build_comms_nccl_only( + &device_resources_[rank], nccl_comms_[rank], num_ranks_, rank); + } + + for (int rank = 0; rank < num_ranks_; rank++) { + RAFT_CUDA_TRY(cudaSetDevice(device_ids_[rank])); + raft::resource::sync_stream(device_resources_[rank]); + } + } + + const raft::device_resources& set_current_device_to_root_rank() const + { + int root_device_id = device_ids_[root_rank_]; + RAFT_CUDA_TRY(cudaSetDevice(root_device_id)); + return device_resources_[root_rank_]; + } + + ~nccl_clique() + { +#pragma omp parallel for // necessary to avoid hangs + for (int rank = 0; rank < num_ranks_; rank++) { + cudaSetDevice(device_ids_[rank]); + ncclCommDestroy(nccl_comms_[rank]); + rmm::cuda_device_id id(device_ids_[rank]); + rmm::mr::set_per_device_resource(id, nullptr); + } + } + + int root_rank_; + int num_ranks_; + int percent_of_free_memory_; + std::vector device_ids_; + std::vector nccl_comms_; + std::vector> per_device_pools_; + std::vector device_resources_; +}; + +} // namespace raft::comms diff --git a/cpp/include/raft/core/device_resources_snmg.hpp b/cpp/include/raft/core/device_resources_snmg.hpp deleted file mode 100644 index f20a81a1c6..0000000000 --- a/cpp/include/raft/core/device_resources_snmg.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2024, NVIDIA CORPORATION. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include -#include - -#include -#include - -/** - * @brief Error checking macro for NCCL runtime API functions. - * - * Invokes a NCCL runtime API function call, if the call does not return ncclSuccess, throws an - * exception detailing the NCCL error that occurred - */ -#define RAFT_NCCL_TRY(call) \ - do { \ - ncclResult_t const status = (call); \ - if (ncclSuccess != status) { \ - std::string msg{}; \ - SET_ERROR_MSG(msg, \ - "NCCL error encountered at: ", \ - "call='%s', Reason=%d:%s", \ - #call, \ - status, \ - ncclGetErrorString(status)); \ - throw raft::logic_error(msg); \ - } \ - } while (0); - -namespace raft { - -/** - * @brief SNMG (single-node multi-GPU) resource container object that stores a NCCL clique and all - * necessary resources used for calling device functions, cuda kernels, libraries and/or NCCL - * communications on each GPU. Note the `device_resources_snmg` object can also be used as a classic - * `device_resources` object. The associated resources will be the ones of the GPU used during - * object instantiation and a GPU switch operation will be ordered during the retrieval of said - * resources. - * - * The `device_resources_snmg` class is intended to be used in a single process to manage several - * GPUs. Please note that NCCL communications are the responsibility of the user. Blocking NCCL - * calls will sometimes require the use of several threads to avoid hangs. - */ -class device_resources_snmg : public device_resources { - public: - /** - * @brief Construct a SNMG resources instance with all available GPUs - */ - device_resources_snmg() : device_resources(), root_rank_(0) - { - cudaGetDevice(&main_gpu_id_); - - int num_ranks; - RAFT_CUDA_TRY(cudaGetDeviceCount(&num_ranks)); - device_ids_.resize(num_ranks); - std::iota(device_ids_.begin(), device_ids_.end(), 0); - nccl_comms_.resize(num_ranks); - initialize(); - } - - /** - * @brief Construct a SNMG resources instance with a subset of available GPUs - * - * @param[in] device_ids List of device IDs to be used by the NCCL clique - */ - device_resources_snmg(const std::vector& device_ids) - : device_resources(), root_rank_(0), device_ids_(device_ids), nccl_comms_(device_ids.size()) - { - cudaGetDevice(&main_gpu_id_); - - initialize(); - } - - /** - * @brief SNMG resources instance copy constructor - * - * @param[in] clique A SNMG resources instance - */ - device_resources_snmg(const device_resources_snmg& clique) - : device_resources(clique), - root_rank_(clique.root_rank_), - main_gpu_id_(clique.main_gpu_id_), - device_ids_(clique.device_ids_), - nccl_comms_(clique.nccl_comms_), - device_resources_(clique.device_resources_) - { - } - - device_resources_snmg(device_resources_snmg&&) = delete; - device_resources_snmg& operator=(device_resources_snmg&&) = delete; - - /** - * @brief Set root rank of NCCL clique - */ - inline int set_root_rank(int rank) { this->root_rank_ = rank; } - - /** - * @brief Get root rank of NCCL clique - */ - inline int get_root_rank() const { return this->root_rank_; } - - /** - * @brief Get number of ranks in NCCL clique - */ - inline int get_num_ranks() const { return this->device_ids_.size(); } - - /** - * @brief Get device ID of rank in NCCL clique - */ - inline int get_device_id(int rank) const { return this->device_ids_[rank]; } - - /** - * @brief Get NCCL comm object of rank in NCCL clique - */ - inline ncclComm_t get_nccl_comm(int rank) const { return this->nccl_comms_[rank]; } - - /** - * @brief Get raft::device_resources object of rank in NCCL clique - */ - inline const raft::device_resources& get_device_resources(int rank) const - { - return this->device_resources_[rank]; - } - - /** - * @brief Set current device ID to root rank and return its raft::device_resources object - */ - inline const raft::device_resources& set_current_device_to_root_rank() const - { - return set_current_device_to_rank(get_root_rank()); - } - - /** - * @brief Set current device ID to rank and return its raft::device_resources object - */ - inline const raft::device_resources& set_current_device_to_rank(int rank) const - { - RAFT_CUDA_TRY(cudaSetDevice(get_device_id(rank))); - return get_device_resources(rank); - } - - /** - * @brief Set a memory pool on all GPUs of the clique - */ - void set_memory_pool(int percent_of_free_memory) const - { - for (int rank = 0; rank < get_num_ranks(); rank++) { - RAFT_CUDA_TRY(cudaSetDevice(get_device_id(rank))); - size_t limit = - rmm::percent_of_free_device_memory(percent_of_free_memory); // check limit for each device - raft::resource::set_workspace_to_pool_resource(get_device_resources(rank), limit); - } - cudaSetDevice(this->main_gpu_id_); - } - - bool has_resource_factory(resource::resource_type resource_type) const override - { - cudaSetDevice(this->main_gpu_id_); - return raft::resources::has_resource_factory(resource_type); - } - - /** Destroys all held-up resources */ - ~device_resources_snmg() - { -#pragma omp parallel for // necessary to avoid hangs - for (int rank = 0; rank < get_num_ranks(); rank++) { - RAFT_CUDA_TRY(cudaSetDevice(get_device_id(rank))); - RAFT_NCCL_TRY(ncclCommDestroy(get_nccl_comm(rank))); - } - cudaSetDevice(this->main_gpu_id_); - } - - private: - /** - * @brief Initializes the NCCL clique and raft::device_resources objects - */ - void initialize() - { - RAFT_NCCL_TRY(ncclCommInitAll(nccl_comms_.data(), get_num_ranks(), device_ids_.data())); - - for (int rank = 0; rank < get_num_ranks(); rank++) { - RAFT_CUDA_TRY(cudaSetDevice(get_device_id(rank))); - device_resources_.emplace_back(); - - // ideally add the ncclComm_t to the device_resources object with - // raft::comms::build_comms_nccl_only - } - cudaSetDevice(this->main_gpu_id_); - } - - int root_rank_; - int main_gpu_id_; - std::vector device_ids_; - std::vector nccl_comms_; - std::vector device_resources_; - -}; // class device_resources_snmg - -} // namespace raft diff --git a/cpp/include/raft/core/resource/nccl_clique.hpp b/cpp/include/raft/core/resource/nccl_clique.hpp new file mode 100644 index 0000000000..edda5043ae --- /dev/null +++ b/cpp/include/raft/core/resource/nccl_clique.hpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +#include + +namespace raft::resource { + +class nccl_clique_resource : public resource { + public: + nccl_clique_resource() : clique_(std::make_unique()) {} + ~nccl_clique_resource() override {} + void* get_resource() override { return clique_.get(); } + + private: + std::unique_ptr clique_; +}; + +/** Factory that knows how to construct a specific raft::resource to populate the res_t. */ +class nccl_clique_resource_factory : public resource_factory { + public: + resource_type get_resource_type() override { return resource_type::NCCL_CLIQUE; } + resource* make_resource() override { return new nccl_clique_resource(); } +}; + +/** + * @defgroup nccl_clique_resource resource functions + * @{ + */ + +/** + * Retrieves a NCCL clique from raft res if it exists, otherwise initializes it and return it. + * + * @param[in] res the raft resources object + * @return NCCL clique + */ +inline const raft::comms::nccl_clique& get_nccl_clique(resources const& res) +{ + if (!res.has_resource_factory(resource_type::NCCL_CLIQUE)) { + res.add_resource_factory(std::make_shared()); + } + return *res.get_resource(resource_type::NCCL_CLIQUE); +}; + +/** + * @} + */ + +} // namespace raft::resource diff --git a/cpp/include/raft/core/resources.hpp b/cpp/include/raft/core/resources.hpp index 44525edb23..b0827d8e11 100644 --- a/cpp/include/raft/core/resources.hpp +++ b/cpp/include/raft/core/resources.hpp @@ -72,7 +72,6 @@ class resources { resources(const resources& res) : factories_(res.factories_), resources_(res.resources_) {} resources(resources&&) = delete; resources& operator=(resources&&) = delete; - virtual ~resources() {} /** * @brief Returns true if a resource_factory has been registered for the @@ -80,7 +79,7 @@ class resources { * @param resource_type resource type to check * @return true if resource_factory is registered for the given resource_type */ - virtual bool has_resource_factory(resource::resource_type resource_type) const + bool has_resource_factory(resource::resource_type resource_type) const { std::lock_guard _(mutex_); return factories_.at(resource_type).first != resource::resource_type::LAST_KEY; diff --git a/cpp/include/raft/neighbors/detail/nn_descent.cuh b/cpp/include/raft/neighbors/detail/nn_descent.cuh index 02610f9afb..64e4a3ea7a 100644 --- a/cpp/include/raft/neighbors/detail/nn_descent.cuh +++ b/cpp/include/raft/neighbors/detail/nn_descent.cuh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, NVIDIA CORPORATION. + * Copyright (c) 2023-2025, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -709,7 +709,8 @@ template > RAFT_KERNEL #ifdef __CUDA_ARCH__ -#if (__CUDA_ARCH__) == 750 || ((__CUDA_ARCH__) >= 860 && (__CUDA_ARCH__) <= 890) +#if (__CUDA_ARCH__) == 750 || ((__CUDA_ARCH__) >= 860 && (__CUDA_ARCH__) <= 890) || \ + (__CUDA_ARCH__) == 1200 __launch_bounds__(BLOCK_SIZE) #else __launch_bounds__(BLOCK_SIZE, 4) diff --git a/cpp/test/CMakeLists.txt b/cpp/tests/CMakeLists.txt similarity index 99% rename from cpp/test/CMakeLists.txt rename to cpp/tests/CMakeLists.txt index 4cd0a32f51..9f96b93e7a 100644 --- a/cpp/test/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -77,7 +77,7 @@ function(ConfigureTest) target_compile_definitions(${TEST_NAME} PRIVATE "RAFT_DISABLE_CUDA") endif() - target_include_directories(${TEST_NAME} PUBLIC "$") + target_include_directories(${TEST_NAME} PUBLIC "$") rapids_test_add( NAME ${TEST_NAME} diff --git a/cpp/test/core/bitmap.cu b/cpp/tests/core/bitmap.cu similarity index 100% rename from cpp/test/core/bitmap.cu rename to cpp/tests/core/bitmap.cu diff --git a/cpp/test/core/bitset.cu b/cpp/tests/core/bitset.cu similarity index 100% rename from cpp/test/core/bitset.cu rename to cpp/tests/core/bitset.cu diff --git a/cpp/test/core/device_resources_manager.cpp b/cpp/tests/core/device_resources_manager.cpp similarity index 100% rename from cpp/test/core/device_resources_manager.cpp rename to cpp/tests/core/device_resources_manager.cpp diff --git a/cpp/test/core/device_setter.cpp b/cpp/tests/core/device_setter.cpp similarity index 100% rename from cpp/test/core/device_setter.cpp rename to cpp/tests/core/device_setter.cpp diff --git a/cpp/test/core/handle.cpp b/cpp/tests/core/handle.cpp similarity index 100% rename from cpp/test/core/handle.cpp rename to cpp/tests/core/handle.cpp diff --git a/cpp/test/core/interruptible.cu b/cpp/tests/core/interruptible.cu similarity index 100% rename from cpp/test/core/interruptible.cu rename to cpp/tests/core/interruptible.cu diff --git a/cpp/test/core/logger.cpp b/cpp/tests/core/logger.cpp similarity index 100% rename from cpp/test/core/logger.cpp rename to cpp/tests/core/logger.cpp diff --git a/cpp/test/core/math_device.cu b/cpp/tests/core/math_device.cu similarity index 100% rename from cpp/test/core/math_device.cu rename to cpp/tests/core/math_device.cu diff --git a/cpp/test/core/math_host.cpp b/cpp/tests/core/math_host.cpp similarity index 100% rename from cpp/test/core/math_host.cpp rename to cpp/tests/core/math_host.cpp diff --git a/cpp/test/core/mdarray.cu b/cpp/tests/core/mdarray.cu similarity index 100% rename from cpp/test/core/mdarray.cu rename to cpp/tests/core/mdarray.cu diff --git a/cpp/test/core/mdbuffer.cu b/cpp/tests/core/mdbuffer.cu similarity index 100% rename from cpp/test/core/mdbuffer.cu rename to cpp/tests/core/mdbuffer.cu diff --git a/cpp/test/core/mdspan_copy.cpp b/cpp/tests/core/mdspan_copy.cpp similarity index 100% rename from cpp/test/core/mdspan_copy.cpp rename to cpp/tests/core/mdspan_copy.cpp diff --git a/cpp/test/core/mdspan_copy.cu b/cpp/tests/core/mdspan_copy.cu similarity index 100% rename from cpp/test/core/mdspan_copy.cu rename to cpp/tests/core/mdspan_copy.cu diff --git a/cpp/test/core/mdspan_utils.cu b/cpp/tests/core/mdspan_utils.cu similarity index 100% rename from cpp/test/core/mdspan_utils.cu rename to cpp/tests/core/mdspan_utils.cu diff --git a/cpp/test/core/memory_type.cpp b/cpp/tests/core/memory_type.cpp similarity index 100% rename from cpp/test/core/memory_type.cpp rename to cpp/tests/core/memory_type.cpp diff --git a/cpp/test/core/numpy_serializer.cu b/cpp/tests/core/numpy_serializer.cu similarity index 100% rename from cpp/test/core/numpy_serializer.cu rename to cpp/tests/core/numpy_serializer.cu diff --git a/cpp/test/core/nvtx.cpp b/cpp/tests/core/nvtx.cpp similarity index 100% rename from cpp/test/core/nvtx.cpp rename to cpp/tests/core/nvtx.cpp diff --git a/cpp/test/core/operators_device.cu b/cpp/tests/core/operators_device.cu similarity index 100% rename from cpp/test/core/operators_device.cu rename to cpp/tests/core/operators_device.cu diff --git a/cpp/test/core/operators_host.cpp b/cpp/tests/core/operators_host.cpp similarity index 100% rename from cpp/test/core/operators_host.cpp rename to cpp/tests/core/operators_host.cpp diff --git a/cpp/test/core/seive.cu b/cpp/tests/core/seive.cu similarity index 100% rename from cpp/test/core/seive.cu rename to cpp/tests/core/seive.cu diff --git a/cpp/test/core/span.cpp b/cpp/tests/core/span.cpp similarity index 100% rename from cpp/test/core/span.cpp rename to cpp/tests/core/span.cpp diff --git a/cpp/test/core/span.cu b/cpp/tests/core/span.cu similarity index 100% rename from cpp/test/core/span.cu rename to cpp/tests/core/span.cu diff --git a/cpp/test/core/sparse_matrix.cpp b/cpp/tests/core/sparse_matrix.cpp similarity index 100% rename from cpp/test/core/sparse_matrix.cpp rename to cpp/tests/core/sparse_matrix.cpp diff --git a/cpp/test/core/sparse_matrix.cu b/cpp/tests/core/sparse_matrix.cu similarity index 100% rename from cpp/test/core/sparse_matrix.cu rename to cpp/tests/core/sparse_matrix.cu diff --git a/cpp/test/core/stream_view.cpp b/cpp/tests/core/stream_view.cpp similarity index 100% rename from cpp/test/core/stream_view.cpp rename to cpp/tests/core/stream_view.cpp diff --git a/cpp/test/core/temporary_device_buffer.cu b/cpp/tests/core/temporary_device_buffer.cu similarity index 100% rename from cpp/test/core/temporary_device_buffer.cu rename to cpp/tests/core/temporary_device_buffer.cu diff --git a/cpp/test/core/test_span.hpp b/cpp/tests/core/test_span.hpp similarity index 100% rename from cpp/test/core/test_span.hpp rename to cpp/tests/core/test_span.hpp diff --git a/cpp/test/ext_headers/00_generate.py b/cpp/tests/ext_headers/00_generate.py similarity index 100% rename from cpp/test/ext_headers/00_generate.py rename to cpp/tests/ext_headers/00_generate.py diff --git a/cpp/test/ext_headers/raft_core_logger.cpp b/cpp/tests/ext_headers/raft_core_logger.cpp similarity index 100% rename from cpp/test/ext_headers/raft_core_logger.cpp rename to cpp/tests/ext_headers/raft_core_logger.cpp diff --git a/cpp/test/ext_headers/raft_distance_detail_pairwise_matrix_dispatch.cu b/cpp/tests/ext_headers/raft_distance_detail_pairwise_matrix_dispatch.cu similarity index 100% rename from cpp/test/ext_headers/raft_distance_detail_pairwise_matrix_dispatch.cu rename to cpp/tests/ext_headers/raft_distance_detail_pairwise_matrix_dispatch.cu diff --git a/cpp/test/ext_headers/raft_distance_distance.cu b/cpp/tests/ext_headers/raft_distance_distance.cu similarity index 100% rename from cpp/test/ext_headers/raft_distance_distance.cu rename to cpp/tests/ext_headers/raft_distance_distance.cu diff --git a/cpp/test/ext_headers/raft_distance_fused_l2_nn.cu b/cpp/tests/ext_headers/raft_distance_fused_l2_nn.cu similarity index 100% rename from cpp/test/ext_headers/raft_distance_fused_l2_nn.cu rename to cpp/tests/ext_headers/raft_distance_fused_l2_nn.cu diff --git a/cpp/test/ext_headers/raft_linalg_detail_coalesced_reduction.cu b/cpp/tests/ext_headers/raft_linalg_detail_coalesced_reduction.cu similarity index 100% rename from cpp/test/ext_headers/raft_linalg_detail_coalesced_reduction.cu rename to cpp/tests/ext_headers/raft_linalg_detail_coalesced_reduction.cu diff --git a/cpp/test/ext_headers/raft_matrix_detail_select_k.cu b/cpp/tests/ext_headers/raft_matrix_detail_select_k.cu similarity index 100% rename from cpp/test/ext_headers/raft_matrix_detail_select_k.cu rename to cpp/tests/ext_headers/raft_matrix_detail_select_k.cu diff --git a/cpp/test/ext_headers/raft_neighbors_ball_cover.cu b/cpp/tests/ext_headers/raft_neighbors_ball_cover.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_ball_cover.cu rename to cpp/tests/ext_headers/raft_neighbors_ball_cover.cu diff --git a/cpp/test/ext_headers/raft_neighbors_brute_force.cu b/cpp/tests/ext_headers/raft_neighbors_brute_force.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_brute_force.cu rename to cpp/tests/ext_headers/raft_neighbors_brute_force.cu diff --git a/cpp/test/ext_headers/raft_neighbors_detail_ivf_flat_interleaved_scan.cu b/cpp/tests/ext_headers/raft_neighbors_detail_ivf_flat_interleaved_scan.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_detail_ivf_flat_interleaved_scan.cu rename to cpp/tests/ext_headers/raft_neighbors_detail_ivf_flat_interleaved_scan.cu diff --git a/cpp/test/ext_headers/raft_neighbors_detail_ivf_flat_search.cu b/cpp/tests/ext_headers/raft_neighbors_detail_ivf_flat_search.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_detail_ivf_flat_search.cu rename to cpp/tests/ext_headers/raft_neighbors_detail_ivf_flat_search.cu diff --git a/cpp/test/ext_headers/raft_neighbors_detail_ivf_pq_compute_similarity.cu b/cpp/tests/ext_headers/raft_neighbors_detail_ivf_pq_compute_similarity.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_detail_ivf_pq_compute_similarity.cu rename to cpp/tests/ext_headers/raft_neighbors_detail_ivf_pq_compute_similarity.cu diff --git a/cpp/test/ext_headers/raft_neighbors_ivf_flat.cu b/cpp/tests/ext_headers/raft_neighbors_ivf_flat.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_ivf_flat.cu rename to cpp/tests/ext_headers/raft_neighbors_ivf_flat.cu diff --git a/cpp/test/ext_headers/raft_neighbors_ivf_pq.cu b/cpp/tests/ext_headers/raft_neighbors_ivf_pq.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_ivf_pq.cu rename to cpp/tests/ext_headers/raft_neighbors_ivf_pq.cu diff --git a/cpp/test/ext_headers/raft_neighbors_refine.cu b/cpp/tests/ext_headers/raft_neighbors_refine.cu similarity index 100% rename from cpp/test/ext_headers/raft_neighbors_refine.cu rename to cpp/tests/ext_headers/raft_neighbors_refine.cu diff --git a/cpp/test/ext_headers/raft_sparse_matrix_detail_select_k.cu b/cpp/tests/ext_headers/raft_sparse_matrix_detail_select_k.cu similarity index 100% rename from cpp/test/ext_headers/raft_sparse_matrix_detail_select_k.cu rename to cpp/tests/ext_headers/raft_sparse_matrix_detail_select_k.cu diff --git a/cpp/test/ext_headers/raft_spatial_knn_detail_ball_cover_registers.cu b/cpp/tests/ext_headers/raft_spatial_knn_detail_ball_cover_registers.cu similarity index 100% rename from cpp/test/ext_headers/raft_spatial_knn_detail_ball_cover_registers.cu rename to cpp/tests/ext_headers/raft_spatial_knn_detail_ball_cover_registers.cu diff --git a/cpp/test/ext_headers/raft_spatial_knn_detail_fused_l2_knn.cu b/cpp/tests/ext_headers/raft_spatial_knn_detail_fused_l2_knn.cu similarity index 100% rename from cpp/test/ext_headers/raft_spatial_knn_detail_fused_l2_knn.cu rename to cpp/tests/ext_headers/raft_spatial_knn_detail_fused_l2_knn.cu diff --git a/cpp/test/label/label.cu b/cpp/tests/label/label.cu similarity index 98% rename from cpp/test/label/label.cu rename to cpp/tests/label/label.cu index 4c3479182f..34a336de59 100644 --- a/cpp/test/label/label.cu +++ b/cpp/tests/label/label.cu @@ -59,8 +59,8 @@ TEST_F(MakeMonotonicTest, Result) ASSERT_TRUE(devArrMatch(actual.data(), expected.data(), m, raft::Compare(), stream)); - delete data_h; - delete expected_h; + delete[] data_h; + delete[] expected_h; } TEST(labelTest, Classlabels) diff --git a/cpp/test/label/merge_labels.cu b/cpp/tests/label/merge_labels.cu similarity index 100% rename from cpp/test/label/merge_labels.cu rename to cpp/tests/label/merge_labels.cu diff --git a/cpp/test/lap/lap.cu b/cpp/tests/lap/lap.cu similarity index 100% rename from cpp/test/lap/lap.cu rename to cpp/tests/lap/lap.cu diff --git a/cpp/test/linalg/add.cu b/cpp/tests/linalg/add.cu similarity index 100% rename from cpp/test/linalg/add.cu rename to cpp/tests/linalg/add.cu diff --git a/cpp/test/linalg/add.cuh b/cpp/tests/linalg/add.cuh similarity index 100% rename from cpp/test/linalg/add.cuh rename to cpp/tests/linalg/add.cuh diff --git a/cpp/test/linalg/axpy.cu b/cpp/tests/linalg/axpy.cu similarity index 100% rename from cpp/test/linalg/axpy.cu rename to cpp/tests/linalg/axpy.cu diff --git a/cpp/test/linalg/binary_op.cu b/cpp/tests/linalg/binary_op.cu similarity index 100% rename from cpp/test/linalg/binary_op.cu rename to cpp/tests/linalg/binary_op.cu diff --git a/cpp/test/linalg/binary_op.cuh b/cpp/tests/linalg/binary_op.cuh similarity index 100% rename from cpp/test/linalg/binary_op.cuh rename to cpp/tests/linalg/binary_op.cuh diff --git a/cpp/test/linalg/cholesky_r1.cu b/cpp/tests/linalg/cholesky_r1.cu similarity index 100% rename from cpp/test/linalg/cholesky_r1.cu rename to cpp/tests/linalg/cholesky_r1.cu diff --git a/cpp/test/linalg/coalesced_reduction.cu b/cpp/tests/linalg/coalesced_reduction.cu similarity index 100% rename from cpp/test/linalg/coalesced_reduction.cu rename to cpp/tests/linalg/coalesced_reduction.cu diff --git a/cpp/test/linalg/divide.cu b/cpp/tests/linalg/divide.cu similarity index 100% rename from cpp/test/linalg/divide.cu rename to cpp/tests/linalg/divide.cu diff --git a/cpp/test/linalg/dot.cu b/cpp/tests/linalg/dot.cu similarity index 100% rename from cpp/test/linalg/dot.cu rename to cpp/tests/linalg/dot.cu diff --git a/cpp/test/linalg/eig.cu b/cpp/tests/linalg/eig.cu similarity index 100% rename from cpp/test/linalg/eig.cu rename to cpp/tests/linalg/eig.cu diff --git a/cpp/test/linalg/eig_sel.cu b/cpp/tests/linalg/eig_sel.cu similarity index 100% rename from cpp/test/linalg/eig_sel.cu rename to cpp/tests/linalg/eig_sel.cu diff --git a/cpp/test/linalg/eigen_solvers.cu b/cpp/tests/linalg/eigen_solvers.cu similarity index 100% rename from cpp/test/linalg/eigen_solvers.cu rename to cpp/tests/linalg/eigen_solvers.cu diff --git a/cpp/test/linalg/eltwise.cu b/cpp/tests/linalg/eltwise.cu similarity index 100% rename from cpp/test/linalg/eltwise.cu rename to cpp/tests/linalg/eltwise.cu diff --git a/cpp/test/linalg/gemm_layout.cu b/cpp/tests/linalg/gemm_layout.cu similarity index 100% rename from cpp/test/linalg/gemm_layout.cu rename to cpp/tests/linalg/gemm_layout.cu diff --git a/cpp/test/linalg/gemv.cu b/cpp/tests/linalg/gemv.cu similarity index 100% rename from cpp/test/linalg/gemv.cu rename to cpp/tests/linalg/gemv.cu diff --git a/cpp/test/linalg/map.cu b/cpp/tests/linalg/map.cu similarity index 100% rename from cpp/test/linalg/map.cu rename to cpp/tests/linalg/map.cu diff --git a/cpp/test/linalg/map_then_reduce.cu b/cpp/tests/linalg/map_then_reduce.cu similarity index 100% rename from cpp/test/linalg/map_then_reduce.cu rename to cpp/tests/linalg/map_then_reduce.cu diff --git a/cpp/test/linalg/matrix_vector.cu b/cpp/tests/linalg/matrix_vector.cu similarity index 100% rename from cpp/test/linalg/matrix_vector.cu rename to cpp/tests/linalg/matrix_vector.cu diff --git a/cpp/test/linalg/matrix_vector_op.cu b/cpp/tests/linalg/matrix_vector_op.cu similarity index 100% rename from cpp/test/linalg/matrix_vector_op.cu rename to cpp/tests/linalg/matrix_vector_op.cu diff --git a/cpp/test/linalg/matrix_vector_op.cuh b/cpp/tests/linalg/matrix_vector_op.cuh similarity index 100% rename from cpp/test/linalg/matrix_vector_op.cuh rename to cpp/tests/linalg/matrix_vector_op.cuh diff --git a/cpp/test/linalg/mean_squared_error.cu b/cpp/tests/linalg/mean_squared_error.cu similarity index 100% rename from cpp/test/linalg/mean_squared_error.cu rename to cpp/tests/linalg/mean_squared_error.cu diff --git a/cpp/test/linalg/multiply.cu b/cpp/tests/linalg/multiply.cu similarity index 100% rename from cpp/test/linalg/multiply.cu rename to cpp/tests/linalg/multiply.cu diff --git a/cpp/test/linalg/norm.cu b/cpp/tests/linalg/norm.cu similarity index 100% rename from cpp/test/linalg/norm.cu rename to cpp/tests/linalg/norm.cu diff --git a/cpp/test/linalg/normalize.cu b/cpp/tests/linalg/normalize.cu similarity index 100% rename from cpp/test/linalg/normalize.cu rename to cpp/tests/linalg/normalize.cu diff --git a/cpp/test/linalg/power.cu b/cpp/tests/linalg/power.cu similarity index 100% rename from cpp/test/linalg/power.cu rename to cpp/tests/linalg/power.cu diff --git a/cpp/test/linalg/randomized_svd.cu b/cpp/tests/linalg/randomized_svd.cu similarity index 100% rename from cpp/test/linalg/randomized_svd.cu rename to cpp/tests/linalg/randomized_svd.cu diff --git a/cpp/test/linalg/reduce.cu b/cpp/tests/linalg/reduce.cu similarity index 100% rename from cpp/test/linalg/reduce.cu rename to cpp/tests/linalg/reduce.cu diff --git a/cpp/test/linalg/reduce.cuh b/cpp/tests/linalg/reduce.cuh similarity index 100% rename from cpp/test/linalg/reduce.cuh rename to cpp/tests/linalg/reduce.cuh diff --git a/cpp/test/linalg/reduce_cols_by_key.cu b/cpp/tests/linalg/reduce_cols_by_key.cu similarity index 100% rename from cpp/test/linalg/reduce_cols_by_key.cu rename to cpp/tests/linalg/reduce_cols_by_key.cu diff --git a/cpp/test/linalg/reduce_rows_by_key.cu b/cpp/tests/linalg/reduce_rows_by_key.cu similarity index 100% rename from cpp/test/linalg/reduce_rows_by_key.cu rename to cpp/tests/linalg/reduce_rows_by_key.cu diff --git a/cpp/test/linalg/rsvd.cu b/cpp/tests/linalg/rsvd.cu similarity index 100% rename from cpp/test/linalg/rsvd.cu rename to cpp/tests/linalg/rsvd.cu diff --git a/cpp/test/linalg/sqrt.cu b/cpp/tests/linalg/sqrt.cu similarity index 100% rename from cpp/test/linalg/sqrt.cu rename to cpp/tests/linalg/sqrt.cu diff --git a/cpp/test/linalg/strided_reduction.cu b/cpp/tests/linalg/strided_reduction.cu similarity index 100% rename from cpp/test/linalg/strided_reduction.cu rename to cpp/tests/linalg/strided_reduction.cu diff --git a/cpp/test/linalg/subtract.cu b/cpp/tests/linalg/subtract.cu similarity index 100% rename from cpp/test/linalg/subtract.cu rename to cpp/tests/linalg/subtract.cu diff --git a/cpp/test/linalg/svd.cu b/cpp/tests/linalg/svd.cu similarity index 100% rename from cpp/test/linalg/svd.cu rename to cpp/tests/linalg/svd.cu diff --git a/cpp/test/linalg/ternary_op.cu b/cpp/tests/linalg/ternary_op.cu similarity index 100% rename from cpp/test/linalg/ternary_op.cu rename to cpp/tests/linalg/ternary_op.cu diff --git a/cpp/test/linalg/transpose.cu b/cpp/tests/linalg/transpose.cu similarity index 100% rename from cpp/test/linalg/transpose.cu rename to cpp/tests/linalg/transpose.cu diff --git a/cpp/test/linalg/unary_op.cu b/cpp/tests/linalg/unary_op.cu similarity index 100% rename from cpp/test/linalg/unary_op.cu rename to cpp/tests/linalg/unary_op.cu diff --git a/cpp/test/linalg/unary_op.cuh b/cpp/tests/linalg/unary_op.cuh similarity index 100% rename from cpp/test/linalg/unary_op.cuh rename to cpp/tests/linalg/unary_op.cuh diff --git a/cpp/test/matrix/argmax.cu b/cpp/tests/matrix/argmax.cu similarity index 100% rename from cpp/test/matrix/argmax.cu rename to cpp/tests/matrix/argmax.cu diff --git a/cpp/test/matrix/argmin.cu b/cpp/tests/matrix/argmin.cu similarity index 100% rename from cpp/test/matrix/argmin.cu rename to cpp/tests/matrix/argmin.cu diff --git a/cpp/test/matrix/columnSort.cu b/cpp/tests/matrix/columnSort.cu similarity index 100% rename from cpp/test/matrix/columnSort.cu rename to cpp/tests/matrix/columnSort.cu diff --git a/cpp/test/matrix/diagonal.cu b/cpp/tests/matrix/diagonal.cu similarity index 100% rename from cpp/test/matrix/diagonal.cu rename to cpp/tests/matrix/diagonal.cu diff --git a/cpp/test/matrix/eye.cu b/cpp/tests/matrix/eye.cu similarity index 100% rename from cpp/test/matrix/eye.cu rename to cpp/tests/matrix/eye.cu diff --git a/cpp/test/matrix/gather.cu b/cpp/tests/matrix/gather.cu similarity index 100% rename from cpp/test/matrix/gather.cu rename to cpp/tests/matrix/gather.cu diff --git a/cpp/test/matrix/linewise_op.cu b/cpp/tests/matrix/linewise_op.cu similarity index 100% rename from cpp/test/matrix/linewise_op.cu rename to cpp/tests/matrix/linewise_op.cu diff --git a/cpp/test/matrix/math.cu b/cpp/tests/matrix/math.cu similarity index 100% rename from cpp/test/matrix/math.cu rename to cpp/tests/matrix/math.cu diff --git a/cpp/test/matrix/matrix.cu b/cpp/tests/matrix/matrix.cu similarity index 100% rename from cpp/test/matrix/matrix.cu rename to cpp/tests/matrix/matrix.cu diff --git a/cpp/test/matrix/norm.cu b/cpp/tests/matrix/norm.cu similarity index 100% rename from cpp/test/matrix/norm.cu rename to cpp/tests/matrix/norm.cu diff --git a/cpp/test/matrix/reverse.cu b/cpp/tests/matrix/reverse.cu similarity index 100% rename from cpp/test/matrix/reverse.cu rename to cpp/tests/matrix/reverse.cu diff --git a/cpp/test/matrix/sample_rows.cu b/cpp/tests/matrix/sample_rows.cu similarity index 100% rename from cpp/test/matrix/sample_rows.cu rename to cpp/tests/matrix/sample_rows.cu diff --git a/cpp/test/matrix/scatter.cu b/cpp/tests/matrix/scatter.cu similarity index 100% rename from cpp/test/matrix/scatter.cu rename to cpp/tests/matrix/scatter.cu diff --git a/cpp/test/matrix/select_k.cu b/cpp/tests/matrix/select_k.cu similarity index 100% rename from cpp/test/matrix/select_k.cu rename to cpp/tests/matrix/select_k.cu diff --git a/cpp/test/matrix/select_k.cuh b/cpp/tests/matrix/select_k.cuh similarity index 100% rename from cpp/test/matrix/select_k.cuh rename to cpp/tests/matrix/select_k.cuh diff --git a/cpp/test/matrix/select_large_k.cu b/cpp/tests/matrix/select_large_k.cu similarity index 100% rename from cpp/test/matrix/select_large_k.cu rename to cpp/tests/matrix/select_large_k.cu diff --git a/cpp/test/matrix/slice.cu b/cpp/tests/matrix/slice.cu similarity index 100% rename from cpp/test/matrix/slice.cu rename to cpp/tests/matrix/slice.cu diff --git a/cpp/test/matrix/triangular.cu b/cpp/tests/matrix/triangular.cu similarity index 100% rename from cpp/test/matrix/triangular.cu rename to cpp/tests/matrix/triangular.cu diff --git a/cpp/test/mr/device/buffer.cpp b/cpp/tests/mr/device/buffer.cpp similarity index 100% rename from cpp/test/mr/device/buffer.cpp rename to cpp/tests/mr/device/buffer.cpp diff --git a/cpp/test/mr/host/buffer.cpp b/cpp/tests/mr/host/buffer.cpp similarity index 100% rename from cpp/test/mr/host/buffer.cpp rename to cpp/tests/mr/host/buffer.cpp diff --git a/cpp/test/neighbors/ball_cover.cu b/cpp/tests/neighbors/ball_cover.cu similarity index 100% rename from cpp/test/neighbors/ball_cover.cu rename to cpp/tests/neighbors/ball_cover.cu diff --git a/cpp/test/neighbors/epsilon_neighborhood.cu b/cpp/tests/neighbors/epsilon_neighborhood.cu similarity index 100% rename from cpp/test/neighbors/epsilon_neighborhood.cu rename to cpp/tests/neighbors/epsilon_neighborhood.cu diff --git a/cpp/test/neighbors/haversine.cu b/cpp/tests/neighbors/haversine.cu similarity index 100% rename from cpp/test/neighbors/haversine.cu rename to cpp/tests/neighbors/haversine.cu diff --git a/cpp/test/neighbors/knn_utils.cuh b/cpp/tests/neighbors/knn_utils.cuh similarity index 100% rename from cpp/test/neighbors/knn_utils.cuh rename to cpp/tests/neighbors/knn_utils.cuh diff --git a/cpp/test/neighbors/spatial_data.h b/cpp/tests/neighbors/spatial_data.h similarity index 100% rename from cpp/test/neighbors/spatial_data.h rename to cpp/tests/neighbors/spatial_data.h diff --git a/cpp/test/random/excess_sampling.cu b/cpp/tests/random/excess_sampling.cu similarity index 100% rename from cpp/test/random/excess_sampling.cu rename to cpp/tests/random/excess_sampling.cu diff --git a/cpp/test/random/make_blobs.cu b/cpp/tests/random/make_blobs.cu similarity index 100% rename from cpp/test/random/make_blobs.cu rename to cpp/tests/random/make_blobs.cu diff --git a/cpp/test/random/make_regression.cu b/cpp/tests/random/make_regression.cu similarity index 100% rename from cpp/test/random/make_regression.cu rename to cpp/tests/random/make_regression.cu diff --git a/cpp/test/random/multi_variable_gaussian.cu b/cpp/tests/random/multi_variable_gaussian.cu similarity index 100% rename from cpp/test/random/multi_variable_gaussian.cu rename to cpp/tests/random/multi_variable_gaussian.cu diff --git a/cpp/test/random/permute.cu b/cpp/tests/random/permute.cu similarity index 100% rename from cpp/test/random/permute.cu rename to cpp/tests/random/permute.cu diff --git a/cpp/test/random/rmat_rectangular_generator.cu b/cpp/tests/random/rmat_rectangular_generator.cu similarity index 100% rename from cpp/test/random/rmat_rectangular_generator.cu rename to cpp/tests/random/rmat_rectangular_generator.cu diff --git a/cpp/test/random/rng.cu b/cpp/tests/random/rng.cu similarity index 100% rename from cpp/test/random/rng.cu rename to cpp/tests/random/rng.cu diff --git a/cpp/test/random/rng_discrete.cu b/cpp/tests/random/rng_discrete.cu similarity index 100% rename from cpp/test/random/rng_discrete.cu rename to cpp/tests/random/rng_discrete.cu diff --git a/cpp/test/random/rng_int.cu b/cpp/tests/random/rng_int.cu similarity index 100% rename from cpp/test/random/rng_int.cu rename to cpp/tests/random/rng_int.cu diff --git a/cpp/test/random/rng_pcg_host_api.cu b/cpp/tests/random/rng_pcg_host_api.cu similarity index 100% rename from cpp/test/random/rng_pcg_host_api.cu rename to cpp/tests/random/rng_pcg_host_api.cu diff --git a/cpp/test/random/sample_without_replacement.cu b/cpp/tests/random/sample_without_replacement.cu similarity index 100% rename from cpp/test/random/sample_without_replacement.cu rename to cpp/tests/random/sample_without_replacement.cu diff --git a/cpp/test/sparse/add.cu b/cpp/tests/sparse/add.cu similarity index 100% rename from cpp/test/sparse/add.cu rename to cpp/tests/sparse/add.cu diff --git a/cpp/test/sparse/convert_coo.cu b/cpp/tests/sparse/convert_coo.cu similarity index 100% rename from cpp/test/sparse/convert_coo.cu rename to cpp/tests/sparse/convert_coo.cu diff --git a/cpp/test/sparse/convert_csr.cu b/cpp/tests/sparse/convert_csr.cu similarity index 100% rename from cpp/test/sparse/convert_csr.cu rename to cpp/tests/sparse/convert_csr.cu diff --git a/cpp/test/sparse/csr_row_slice.cu b/cpp/tests/sparse/csr_row_slice.cu similarity index 100% rename from cpp/test/sparse/csr_row_slice.cu rename to cpp/tests/sparse/csr_row_slice.cu diff --git a/cpp/test/sparse/csr_to_dense.cu b/cpp/tests/sparse/csr_to_dense.cu similarity index 100% rename from cpp/test/sparse/csr_to_dense.cu rename to cpp/tests/sparse/csr_to_dense.cu diff --git a/cpp/test/sparse/csr_transpose.cu b/cpp/tests/sparse/csr_transpose.cu similarity index 100% rename from cpp/test/sparse/csr_transpose.cu rename to cpp/tests/sparse/csr_transpose.cu diff --git a/cpp/test/sparse/degree.cu b/cpp/tests/sparse/degree.cu similarity index 100% rename from cpp/test/sparse/degree.cu rename to cpp/tests/sparse/degree.cu diff --git a/cpp/test/sparse/dist_coo_spmv.cu b/cpp/tests/sparse/dist_coo_spmv.cu similarity index 100% rename from cpp/test/sparse/dist_coo_spmv.cu rename to cpp/tests/sparse/dist_coo_spmv.cu diff --git a/cpp/test/sparse/distance.cu b/cpp/tests/sparse/distance.cu similarity index 100% rename from cpp/test/sparse/distance.cu rename to cpp/tests/sparse/distance.cu diff --git a/cpp/test/sparse/filter.cu b/cpp/tests/sparse/filter.cu similarity index 100% rename from cpp/test/sparse/filter.cu rename to cpp/tests/sparse/filter.cu diff --git a/cpp/test/sparse/masked_matmul.cu b/cpp/tests/sparse/masked_matmul.cu similarity index 100% rename from cpp/test/sparse/masked_matmul.cu rename to cpp/tests/sparse/masked_matmul.cu diff --git a/cpp/test/sparse/mst.cu b/cpp/tests/sparse/mst.cu similarity index 100% rename from cpp/test/sparse/mst.cu rename to cpp/tests/sparse/mst.cu diff --git a/cpp/test/sparse/norm.cu b/cpp/tests/sparse/norm.cu similarity index 100% rename from cpp/test/sparse/norm.cu rename to cpp/tests/sparse/norm.cu diff --git a/cpp/test/sparse/normalize.cu b/cpp/tests/sparse/normalize.cu similarity index 100% rename from cpp/test/sparse/normalize.cu rename to cpp/tests/sparse/normalize.cu diff --git a/cpp/test/sparse/reduce.cu b/cpp/tests/sparse/reduce.cu similarity index 100% rename from cpp/test/sparse/reduce.cu rename to cpp/tests/sparse/reduce.cu diff --git a/cpp/test/sparse/row_op.cu b/cpp/tests/sparse/row_op.cu similarity index 100% rename from cpp/test/sparse/row_op.cu rename to cpp/tests/sparse/row_op.cu diff --git a/cpp/test/sparse/sddmm.cu b/cpp/tests/sparse/sddmm.cu similarity index 100% rename from cpp/test/sparse/sddmm.cu rename to cpp/tests/sparse/sddmm.cu diff --git a/cpp/test/sparse/select_k_csr.cu b/cpp/tests/sparse/select_k_csr.cu similarity index 100% rename from cpp/test/sparse/select_k_csr.cu rename to cpp/tests/sparse/select_k_csr.cu diff --git a/cpp/test/sparse/solver/lanczos.cu b/cpp/tests/sparse/solver/lanczos.cu similarity index 100% rename from cpp/test/sparse/solver/lanczos.cu rename to cpp/tests/sparse/solver/lanczos.cu diff --git a/cpp/test/sparse/sort.cu b/cpp/tests/sparse/sort.cu similarity index 100% rename from cpp/test/sparse/sort.cu rename to cpp/tests/sparse/sort.cu diff --git a/cpp/test/sparse/spectral_matrix.cu b/cpp/tests/sparse/spectral_matrix.cu similarity index 100% rename from cpp/test/sparse/spectral_matrix.cu rename to cpp/tests/sparse/spectral_matrix.cu diff --git a/cpp/test/sparse/spgemmi.cu b/cpp/tests/sparse/spgemmi.cu similarity index 100% rename from cpp/test/sparse/spgemmi.cu rename to cpp/tests/sparse/spgemmi.cu diff --git a/cpp/test/sparse/spmm.cu b/cpp/tests/sparse/spmm.cu similarity index 100% rename from cpp/test/sparse/spmm.cu rename to cpp/tests/sparse/spmm.cu diff --git a/cpp/test/sparse/symmetrize.cu b/cpp/tests/sparse/symmetrize.cu similarity index 100% rename from cpp/test/sparse/symmetrize.cu rename to cpp/tests/sparse/symmetrize.cu diff --git a/cpp/test/stats/accuracy.cu b/cpp/tests/stats/accuracy.cu similarity index 100% rename from cpp/test/stats/accuracy.cu rename to cpp/tests/stats/accuracy.cu diff --git a/cpp/test/stats/adjusted_rand_index.cu b/cpp/tests/stats/adjusted_rand_index.cu similarity index 100% rename from cpp/test/stats/adjusted_rand_index.cu rename to cpp/tests/stats/adjusted_rand_index.cu diff --git a/cpp/test/stats/completeness_score.cu b/cpp/tests/stats/completeness_score.cu similarity index 100% rename from cpp/test/stats/completeness_score.cu rename to cpp/tests/stats/completeness_score.cu diff --git a/cpp/test/stats/contingencyMatrix.cu b/cpp/tests/stats/contingencyMatrix.cu similarity index 100% rename from cpp/test/stats/contingencyMatrix.cu rename to cpp/tests/stats/contingencyMatrix.cu diff --git a/cpp/test/stats/cov.cu b/cpp/tests/stats/cov.cu similarity index 100% rename from cpp/test/stats/cov.cu rename to cpp/tests/stats/cov.cu diff --git a/cpp/test/stats/dispersion.cu b/cpp/tests/stats/dispersion.cu similarity index 100% rename from cpp/test/stats/dispersion.cu rename to cpp/tests/stats/dispersion.cu diff --git a/cpp/test/stats/entropy.cu b/cpp/tests/stats/entropy.cu similarity index 100% rename from cpp/test/stats/entropy.cu rename to cpp/tests/stats/entropy.cu diff --git a/cpp/test/stats/histogram.cu b/cpp/tests/stats/histogram.cu similarity index 100% rename from cpp/test/stats/histogram.cu rename to cpp/tests/stats/histogram.cu diff --git a/cpp/test/stats/homogeneity_score.cu b/cpp/tests/stats/homogeneity_score.cu similarity index 100% rename from cpp/test/stats/homogeneity_score.cu rename to cpp/tests/stats/homogeneity_score.cu diff --git a/cpp/test/stats/information_criterion.cu b/cpp/tests/stats/information_criterion.cu similarity index 100% rename from cpp/test/stats/information_criterion.cu rename to cpp/tests/stats/information_criterion.cu diff --git a/cpp/test/stats/kl_divergence.cu b/cpp/tests/stats/kl_divergence.cu similarity index 100% rename from cpp/test/stats/kl_divergence.cu rename to cpp/tests/stats/kl_divergence.cu diff --git a/cpp/test/stats/mean.cu b/cpp/tests/stats/mean.cu similarity index 100% rename from cpp/test/stats/mean.cu rename to cpp/tests/stats/mean.cu diff --git a/cpp/test/stats/mean_center.cu b/cpp/tests/stats/mean_center.cu similarity index 100% rename from cpp/test/stats/mean_center.cu rename to cpp/tests/stats/mean_center.cu diff --git a/cpp/test/stats/meanvar.cu b/cpp/tests/stats/meanvar.cu similarity index 100% rename from cpp/test/stats/meanvar.cu rename to cpp/tests/stats/meanvar.cu diff --git a/cpp/test/stats/minmax.cu b/cpp/tests/stats/minmax.cu similarity index 100% rename from cpp/test/stats/minmax.cu rename to cpp/tests/stats/minmax.cu diff --git a/cpp/test/stats/mutual_info_score.cu b/cpp/tests/stats/mutual_info_score.cu similarity index 100% rename from cpp/test/stats/mutual_info_score.cu rename to cpp/tests/stats/mutual_info_score.cu diff --git a/cpp/test/stats/r2_score.cu b/cpp/tests/stats/r2_score.cu similarity index 100% rename from cpp/test/stats/r2_score.cu rename to cpp/tests/stats/r2_score.cu diff --git a/cpp/test/stats/rand_index.cu b/cpp/tests/stats/rand_index.cu similarity index 100% rename from cpp/test/stats/rand_index.cu rename to cpp/tests/stats/rand_index.cu diff --git a/cpp/test/stats/regression_metrics.cu b/cpp/tests/stats/regression_metrics.cu similarity index 100% rename from cpp/test/stats/regression_metrics.cu rename to cpp/tests/stats/regression_metrics.cu diff --git a/cpp/test/stats/stddev.cu b/cpp/tests/stats/stddev.cu similarity index 100% rename from cpp/test/stats/stddev.cu rename to cpp/tests/stats/stddev.cu diff --git a/cpp/test/stats/sum.cu b/cpp/tests/stats/sum.cu similarity index 100% rename from cpp/test/stats/sum.cu rename to cpp/tests/stats/sum.cu diff --git a/cpp/test/stats/v_measure.cu b/cpp/tests/stats/v_measure.cu similarity index 100% rename from cpp/test/stats/v_measure.cu rename to cpp/tests/stats/v_measure.cu diff --git a/cpp/test/stats/weighted_mean.cu b/cpp/tests/stats/weighted_mean.cu similarity index 100% rename from cpp/test/stats/weighted_mean.cu rename to cpp/tests/stats/weighted_mean.cu diff --git a/cpp/test/test.cpp b/cpp/tests/test.cpp similarity index 100% rename from cpp/test/test.cpp rename to cpp/tests/test.cpp diff --git a/cpp/test/test_utils.cuh b/cpp/tests/test_utils.cuh similarity index 100% rename from cpp/test/test_utils.cuh rename to cpp/tests/test_utils.cuh diff --git a/cpp/test/test_utils.h b/cpp/tests/test_utils.h similarity index 100% rename from cpp/test/test_utils.h rename to cpp/tests/test_utils.h diff --git a/cpp/test/util/bitonic_sort.cu b/cpp/tests/util/bitonic_sort.cu similarity index 100% rename from cpp/test/util/bitonic_sort.cu rename to cpp/tests/util/bitonic_sort.cu diff --git a/cpp/test/util/cudart_utils.cpp b/cpp/tests/util/cudart_utils.cpp similarity index 100% rename from cpp/test/util/cudart_utils.cpp rename to cpp/tests/util/cudart_utils.cpp diff --git a/cpp/test/util/device_atomics.cu b/cpp/tests/util/device_atomics.cu similarity index 100% rename from cpp/test/util/device_atomics.cu rename to cpp/tests/util/device_atomics.cu diff --git a/cpp/test/util/integer_utils.cpp b/cpp/tests/util/integer_utils.cpp similarity index 100% rename from cpp/test/util/integer_utils.cpp rename to cpp/tests/util/integer_utils.cpp diff --git a/cpp/test/util/integer_utils.cu b/cpp/tests/util/integer_utils.cu similarity index 100% rename from cpp/test/util/integer_utils.cu rename to cpp/tests/util/integer_utils.cu diff --git a/cpp/test/util/memory_type_dispatcher.cu b/cpp/tests/util/memory_type_dispatcher.cu similarity index 100% rename from cpp/test/util/memory_type_dispatcher.cu rename to cpp/tests/util/memory_type_dispatcher.cu diff --git a/cpp/test/util/popc.cu b/cpp/tests/util/popc.cu similarity index 100% rename from cpp/test/util/popc.cu rename to cpp/tests/util/popc.cu diff --git a/cpp/test/util/pow2_utils.cu b/cpp/tests/util/pow2_utils.cu similarity index 100% rename from cpp/test/util/pow2_utils.cu rename to cpp/tests/util/pow2_utils.cu diff --git a/cpp/test/util/reduction.cu b/cpp/tests/util/reduction.cu similarity index 100% rename from cpp/test/util/reduction.cu rename to cpp/tests/util/reduction.cu diff --git a/dependencies.yaml b/dependencies.yaml index 689cf8414c..b7a0344b1a 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -6,6 +6,8 @@ files: cuda: ["11.8", "12.5"] arch: [x86_64, aarch64] includes: + - build_common + - build_cython - checks - cuda - cuda_version @@ -15,7 +17,6 @@ files: - depends_on_rmm - develop - docs - - rapids_build - rapids_build_skbuild - run_pylibraft - run_raft_dask @@ -48,6 +49,29 @@ files: - docs - py_version - test_pylibraft + py_build_libraft: + output: pyproject + pyproject_dir: python/libraft + extras: + table: build-system + includes: + - rapids_build_skbuild + py_rapids_build_libraft: + output: pyproject + pyproject_dir: python/libraft + extras: + table: tool.rapids-build-backend + key: requires + includes: + - build_common + - depends_on_librmm + py_run_libraft: + output: pyproject + pyproject_dir: python/libraft + extras: + table: project + includes: + - cuda_wheels py_build_pylibraft: output: pyproject pyproject_dir: python/pylibraft @@ -62,16 +86,19 @@ files: table: tool.rapids-build-backend key: requires includes: + - build_common + - build_cython + - depends_on_libraft + - depends_on_librmm - depends_on_cuda_python - depends_on_rmm - - rapids_build py_run_pylibraft: output: pyproject pyproject_dir: python/pylibraft extras: table: project includes: - - cuda_wheels + - depends_on_libraft - depends_on_cuda_python - depends_on_rmm - run_pylibraft @@ -99,8 +126,11 @@ files: table: tool.rapids-build-backend key: requires includes: + - build_common + - build_cython + - depends_on_libraft + - depends_on_librmm - depends_on_ucx_build - - rapids_build py_run_raft_dask: output: pyproject pyproject_dir: python/raft-dask @@ -108,6 +138,7 @@ files: table: project includes: - depends_on_distributed_ucxx + - depends_on_libraft - run_raft_dask py_test_raft_dask: output: pyproject @@ -135,12 +166,11 @@ dependencies: - output_types: [requirements, pyproject] packages: - scikit-build-core[pyproject]>=0.10.0 - rapids_build: + build_common: common: - output_types: [conda, requirements, pyproject] packages: - &cmake_ver cmake>=3.26.4,!=3.30.0 - - cython>=3.0.0,<3.1.0a0 - ninja - output_types: [conda] packages: @@ -154,14 +184,28 @@ dependencies: matrices: - matrix: arch: x86_64 + cuda: "11.8" packages: - gcc_linux-64=11.* - - sysroot_linux-64==2.17 + - sysroot_linux-64==2.28 - matrix: arch: aarch64 + cuda: "11.8" packages: - gcc_linux-aarch64=11.* - - sysroot_linux-aarch64==2.17 + - sysroot_linux-aarch64==2.28 + - matrix: + arch: x86_64 + cuda: "12.*" + packages: + - gcc_linux-64=13.* + - sysroot_linux-64==2.28 + - matrix: + arch: aarch64 + cuda: "12.*" + packages: + - gcc_linux-aarch64=13.* + - sysroot_linux-aarch64==2.28 - output_types: conda matrices: - matrix: {cuda: "12.*"} @@ -182,7 +226,11 @@ dependencies: packages: [nvcc_linux-64=11.2] - matrix: {cuda: "11.2", arch: aarch64} packages: [nvcc_linux-aarch64=11.2] - + build_cython: + common: + - output_types: [conda, requirements, pyproject] + packages: + - cython>=3.0.0,<3.1.0a0 checks: common: - output_types: [conda, requirements] @@ -310,11 +358,14 @@ dependencies: - nvidia-curand-cu12 - nvidia-cusolver-cu12 - nvidia-cusparse-cu12 - # CUDA 11 does not provide wheels, so use the system libraries instead - matrix: cuda: "11.*" use_cuda_wheels: "true" packages: + - nvidia-cublas-cu11 + - nvidia-curand-cu11 + - nvidia-cusolver-cu11 + - nvidia-cusparse-cu11 # if use_cuda_wheels=false is provided, do not add dependencies on any CUDA wheels # (e.g. for DLFW and pip devcontainers) - matrix: @@ -471,6 +522,55 @@ dependencies: packages: - distributed-ucxx-cu11==0.42.*,>=0.0.0a0 - {matrix: null, packages: [*distributed_ucxx_unsuffixed]} + depends_on_libraft: + common: + - 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.*" + cuda_suffixed: "true" + packages: + - libraft-cu12==25.2.*,>=0.0.0a0 + - matrix: + cuda: "11.*" + cuda_suffixed: "true" + packages: + - libraft-cu11==25.2.*,>=0.0.0a0 + - matrix: + packages: + - libraft==25.2.*,>=0.0.0a0 + depends_on_librmm: + common: + - output_types: conda + packages: + - &librmm_unsuffixed librmm==25.2.*,>=0.0.0a0 + - 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.*" + cuda_suffixed: "true" + packages: + - librmm-cu12==25.2.*,>=0.0.0a0 + - matrix: + cuda: "11.*" + cuda_suffixed: "true" + packages: + - librmm-cu11==25.2.*,>=0.0.0a0 + - matrix: + packages: + - *librmm_unsuffixed depends_on_rmm: common: - output_types: conda diff --git a/docs/source/cpp_api/core_resources.rst b/docs/source/cpp_api/core_resources.rst index 3c242af848..0da11acae6 100644 --- a/docs/source/cpp_api/core_resources.rst +++ b/docs/source/cpp_api/core_resources.rst @@ -55,23 +55,6 @@ namespace *raft::core* :project: RAFT :members: -SNMG Device Resources ---------------------- - -The `raft::device_resources_snmg` provides a convenient way to design SNMG -(single-node multi-GPU) algorithms. It initiates device-related resources -for a set of devices forming clique. This includes NCCL communications. -GPUs can be addressed and exchanges be made over multiple threads -for performance or convenience. - -``#include `` - -namespace *raft::core* - -.. doxygenclass:: raft::device_resources_snmg - :project: RAFT - :members: - Resource Functions ------------------ diff --git a/docs/source/developer_guide.md b/docs/source/developer_guide.md index 6240b2638b..1a2626f2b2 100644 --- a/docs/source/developer_guide.md +++ b/docs/source/developer_guide.md @@ -211,7 +211,7 @@ This will bring up an interactive prompt to select which spelling fixes to apply Manually, run the following to bulk-fix include style issues: ```bash -python ./cpp/scripts/include_checker.py --inplace [cpp/include cpp/test ... list of folders which you want to fix] +python ./cpp/scripts/include_checker.py --inplace [cpp/include cpp/tests ... list of folders which you want to fix] ``` ### Copyright header @@ -298,9 +298,9 @@ RAFT is a heavily templated library. Several core functions are expensive to com **Macros.** We define the macros `RAFT_COMPILED` and `RAFT_EXPLICIT_INSTANTIATE_ONLY`. The `RAFT_COMPILED` macro is defined by `CMake` when compiling code that (1) is part of `libraft.so` or (2) is linked with `libraft.so`. It indicates that a precompiled `libraft.so` is present at runtime. -The `RAFT_EXPLICIT_INSTANTIATE_ONLY` macro is defined by `CMake` during compilation of `libraft.so` itself. When defined, it indicates that implicit instantiations of expensive function templates are forbidden (they result in a compiler error). In the RAFT project, we additionally define this macro during compilation of the tests and benchmarks. +The `RAFT_EXPLICIT_INSTANTIATE_ONLY` macro is defined by `CMake` during compilation of `libraft.so` itself. When defined, it indicates that implicit instantiations of expensive function templates are forbidden (they result in a compiler error). In the RAFT project, we additionally define this macro during compilation of the tests and benchmarks. -Below, we summarize which combinations of `RAFT_COMPILED` and `RAFT_EXPLICIT_INSTANTIATE_ONLY` are used in practice and what the effect of the combination is. +Below, we summarize which combinations of `RAFT_COMPILED` and `RAFT_EXPLICIT_INSTANTIATE_ONLY` are used in practice and what the effect of the combination is. | RAFT_COMPILED | RAFT_EXPLICIT_INSTANTIATE_ONLY | Which targets | |---------------|--------------------------------|------------------------------------------------------------------------------------------------------| @@ -349,7 +349,7 @@ The file `expensive-ext.cuh` contains the following: #ifdef RAFT_EXPLICIT_INSTANTIATE_ONLY namespace raft { -// (1) define templates to raise an error in case of accidental instantiation +// (1) define templates to raise an error in case of accidental instantiation template void expensive(T arg) RAFT_EXPLICIT; } // namespace raft #endif //RAFT_EXPLICIT_INSTANTIATE_ONLY @@ -371,7 +371,7 @@ template void raft::expensive(int); template void raft::expensive(float); ``` -**Design considerations**: +**Design considerations**: 1. In the `-ext.cuh` header, do not include implementation headers. Only include function parameter types and types that are used to instantiate the templates. If a primitive takes custom parameter types, define them in a separate header called `_types.hpp`. (see [Common Design Considerations](https://github.com/rapidsai/raft/blob/7b065aff81a0b1976e2a9e2f3de6690361a1111b/docs/source/developer_guide.md#common-design-considerations)). @@ -381,7 +381,7 @@ template void raft::expensive(float); 4. If a header file defines multiple expensive templates, it can be that one of them is not instantiated. In this case, **do define** the template with `RAFT_EXPLICIT` in the `-ext` header. This way, when the template is instantiated, the developer gets a helpful error message instead of a confusing "function not found". -This header structure was proposed in [issue #1416](https://github.com/rapidsai/raft/issues/1416), which contains more background on the motivation of this structure and the mechanics of C++ template instantiation. +This header structure was proposed in [issue #1416](https://github.com/rapidsai/raft/issues/1416), which contains more background on the motivation of this structure and the mechanics of C++ template instantiation. ## Testing diff --git a/pyproject.toml b/pyproject.toml index 2f23debfbe..460c0312a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ ignore_missing_imports = true # they are imported by a checked file. follow_imports = "skip" exclude = [ - "pylibraft/pylibraft/test", + "pylibraft/pylibraft/tests", ] [tool.codespell] diff --git a/python/libraft/CMakeLists.txt b/python/libraft/CMakeLists.txt new file mode 100644 index 0000000000..db81aa9507 --- /dev/null +++ b/python/libraft/CMakeLists.txt @@ -0,0 +1,56 @@ +# ============================================================================= +# Copyright (c) 2025, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing permissions and limitations under +# the License. +# ============================================================================= + +cmake_minimum_required(VERSION 3.26.4 FATAL_ERROR) + +include(../../rapids_config.cmake) + +project( + libraft-python + VERSION "${RAPIDS_VERSION}" + LANGUAGES CXX +) + +# Check if raft is already available. If so, it is the user's responsibility to ensure that the +# CMake package is also available at build time of the Python raft package. +find_package(raft "${RAPIDS_VERSION}") + +if(raft_FOUND) + return() +endif() + +unset(raft_FOUND) + +# --- CUDA --- # +set(CUDA_STATIC_RUNTIME ON) +set(CUDA_STATIC_MATH_LIBRARIES OFF) + +# --- RAFT ---# +set(BUILD_TESTS OFF) +set(BUILD_PRIMS_BENCH OFF) +set(RAFT_COMPILE_DYNAMIC_ONLY ON) +set(RAFT_COMPILE_LIBRARY ON) + +add_subdirectory(../../cpp raft-cpp) + +# assumes libraft.so is installed 2 levels deep, e.g. site-packages/libraft/lib64/libraft.so +set_property( + TARGET raft_lib + PROPERTY INSTALL_RPATH + "$ORIGIN/../../nvidia/cublas/lib" + "$ORIGIN/../../nvidia/curand/lib" + "$ORIGIN/../../nvidia/cusolver/lib" + "$ORIGIN/../../nvidia/cusparse/lib" + "$ORIGIN/../../nvidia/nvjitlink/lib" +) diff --git a/python/libraft/LICENSE b/python/libraft/LICENSE new file mode 120000 index 0000000000..30cff7403d --- /dev/null +++ b/python/libraft/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/python/libraft/README.md b/python/libraft/README.md new file mode 120000 index 0000000000..fe84005413 --- /dev/null +++ b/python/libraft/README.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file diff --git a/python/libraft/libraft/VERSION b/python/libraft/libraft/VERSION new file mode 120000 index 0000000000..d62dc733ef --- /dev/null +++ b/python/libraft/libraft/VERSION @@ -0,0 +1 @@ +../../../VERSION \ No newline at end of file diff --git a/python/libraft/libraft/__init__.py b/python/libraft/libraft/__init__.py new file mode 100644 index 0000000000..9260f4e67c --- /dev/null +++ b/python/libraft/libraft/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2025, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from libraft._version import __git_commit__, __version__ +from libraft.load import load_library diff --git a/python/libraft/libraft/_version.py b/python/libraft/libraft/_version.py new file mode 100644 index 0000000000..530bf8bea6 --- /dev/null +++ b/python/libraft/libraft/_version.py @@ -0,0 +1,33 @@ +# Copyright (c) 2025, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import importlib.resources + +__version__ = ( + importlib.resources.files(__package__) + .joinpath("VERSION") + .read_text() + .strip() +) +try: + __git_commit__ = ( + importlib.resources.files(__package__) + .joinpath("GIT_COMMIT") + .read_text() + .strip() + ) +except FileNotFoundError: + __git_commit__ = "" + +__all__ = ["__git_commit__", "__version__"] diff --git a/python/libraft/libraft/load.py b/python/libraft/libraft/load.py new file mode 100644 index 0000000000..ad3db9e09c --- /dev/null +++ b/python/libraft/libraft/load.py @@ -0,0 +1,80 @@ +# Copyright (c) 2025, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import ctypes +import os + +# Loading with RTLD_LOCAL adds the library itself to the loader's +# loaded library cache without loading any symbols into the global +# namespace. This allows libraries that express a dependency on +# this library to be loaded later and successfully satisfy this dependency +# without polluting the global symbol table with symbols from +# libraft that could conflict with symbols from other DSOs. +PREFERRED_LOAD_FLAG = ctypes.RTLD_LOCAL + + +def _load_system_installation(soname: str): + """Try to dlopen() the library indicated by ``soname`` + Raises ``OSError`` if library cannot be loaded. + """ + return ctypes.CDLL(soname, PREFERRED_LOAD_FLAG) + + +def _load_wheel_installation(soname: str): + """Try to dlopen() the library indicated by ``soname`` + Returns ``None`` if the library cannot be loaded. + """ + if os.path.isfile( + lib := os.path.join(os.path.dirname(__file__), "lib64", soname) + ): + return ctypes.CDLL(lib, PREFERRED_LOAD_FLAG) + return None + + +def load_library(): + """Dynamically load libraft.so and its dependencies""" + prefer_system_installation = ( + os.getenv("RAPIDS_LIBRAFT_PREFER_SYSTEM_LIBRARY", "false").lower() + != "false" + ) + + soname = "libraft.so" + libraft_lib = None + if prefer_system_installation: + # Prefer a system library if one is present to + # avoid clobbering symbols that other packages might expect, but if no + # other library is present use the one in the wheel. + try: + libraft_lib = _load_system_installation(soname) + except OSError: + libraft_lib = _load_wheel_installation(soname) + else: + # Prefer the libraries bundled in this package. If they aren't found + # (which might be the case in builds where the library was prebuilt + # before packaging the wheel), look for a system installation. + try: + libraft_lib = _load_wheel_installation(soname) + if libraft_lib is None: + libraft_lib = _load_system_installation(soname) + except OSError: + # If none of the searches above succeed, just silently return None + # and rely on other mechanisms (like RPATHs on other DSOs) to + # help the loader find the library. + pass + + # The caller almost never needs to do anything with this library, but no + # harm in offering the option since this object at least provides a handle + # to inspect where libraft was loaded from. + return libraft_lib diff --git a/python/libraft/pyproject.toml b/python/libraft/pyproject.toml new file mode 100644 index 0000000000..89b2834614 --- /dev/null +++ b/python/libraft/pyproject.toml @@ -0,0 +1,117 @@ +# Copyright (c) 2025, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[build-system] + +requires = [ + "rapids-build-backend>=0.3.0,<0.4.0.dev0", + "scikit-build-core[pyproject]>=0.10.0", +] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. +build-backend = "rapids_build_backend.build" + +[project] +name = "libraft" +dynamic = ["version"] +description = "RAFT: Reusable Algorithms Functions and other Tools (C++)" +readme = { file = "README.md", content-type = "text/markdown" } +authors = [ + { name = "NVIDIA Corporation" }, +] +license = { text = "Apache 2.0" } +requires-python = ">=3.10" +dependencies = [ + "nvidia-cublas", + "nvidia-curand", + "nvidia-cusolver", + "nvidia-cusparse", +] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. +classifiers = [ + "Intended Audience :: Developers", +] + +[project.urls] +Homepage = "https://github.com/rapidsai/raft" +Documentation = "https://docs.rapids.ai/api/raft/stable/" + +[project.entry-points."cmake.prefix"] +libraft = "libraft" + +[tool.isort] +line_length = 79 +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +combine_as_imports = true +order_by_type = true +known_first_party = [ + "libraft", +] +default_section = "THIRDPARTY" +sections = [ + "FUTURE", + "STDLIB", + "THIRDPARTY", + "DASK", + "RAPIDS", + "FIRSTPARTY", + "LOCALFOLDER", +] +skip = [ + "thirdparty", + ".eggs", + ".git", + ".hg", + ".mypy_cache", + ".tox", + ".venv", + "_build", + "buck-out", + "build", + "dist", + "__init__.py", +] + +[tool.scikit-build] +build-dir = "build/{wheel_tag}" +cmake.build-type = "Release" +cmake.version = "CMakeLists.txt" +minimum-version = "build-system.requires" +ninja.make-fallback = true +sdist.reproducible = true +wheel.install-dir = "libraft" +wheel.packages = ["libraft"] +wheel.py-api = "py3" + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "libraft/VERSION" +regex = "(?P.*)" + +[tool.rapids-build-backend] +build-backend = "scikit_build_core.build" +requires = [ + "cmake>=3.26.4,!=3.30.0", + "librmm==25.2.*,>=0.0.0a0", + "ninja", +] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. +dependencies-file = "../../dependencies.yaml" +matrix-entry = "cuda_suffixed=true;use_cuda_wheels=true" + +[tool.pydistcheck] +select = [ + "distro-too-large-compressed", +] + +# PyPI limit is 100 MiB, fail CI before we get too close to that +max_allowed_size_compressed = '75M' diff --git a/python/pylibraft/CMakeLists.txt b/python/pylibraft/CMakeLists.txt index 758c1e4711..83c262dc10 100644 --- a/python/pylibraft/CMakeLists.txt +++ b/python/pylibraft/CMakeLists.txt @@ -27,68 +27,13 @@ project( LANGUAGES CXX CUDA ) -option(FIND_RAFT_CPP "Search for existing RAFT C++ installations before defaulting to local files" - ON -) -option(USE_CUDA_MATH_WHEELS "Use the CUDA math wheels instead of the system libraries" OFF) - -# If the user requested it we attempt to find RAFT. -if(FIND_RAFT_CPP) - find_package(raft "${RAPIDS_VERSION}" REQUIRED COMPONENTS compiled) - if(NOT TARGET raft::raft_lib) - message( - FATAL_ERROR - "Building against a preexisting libraft library requires the compiled libraft to have been built!" - ) - - endif() -else() - set(raft_FOUND OFF) -endif() +# an installed version of raft contains the other necessary targets (like CCCL and cuco) +find_package(raft "${RAPIDS_VERSION}" REQUIRED COMPONENTS raft compiled) include(rapids-cython-core) -if(NOT raft_FOUND) - find_package(CUDAToolkit REQUIRED) - - set(BUILD_TESTS OFF) - set(BUILD_PRIMS_BENCH OFF) - set(RAFT_COMPILE_LIBRARY ON) - set(CUDA_STATIC_RUNTIME ON) - set(CUDA_STATIC_MATH_LIBRARIES ON) - if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 12.0) - set(CUDA_STATIC_MATH_LIBRARIES OFF) - elseif(USE_CUDA_MATH_WHEELS) - message(FATAL_ERROR "Cannot use CUDA math wheels with CUDA < 12.0") - endif() - - add_subdirectory(../../cpp raft-cpp EXCLUDE_FROM_ALL) - - if(NOT CUDA_STATIC_MATH_LIBRARIES AND USE_CUDA_MATH_WHEELS) - set_property( - TARGET raft_lib - PROPERTY INSTALL_RPATH - "$ORIGIN/../nvidia/cublas/lib" - "$ORIGIN/../nvidia/curand/lib" - "$ORIGIN/../nvidia/cusolver/lib" - "$ORIGIN/../nvidia/cusparse/lib" - "$ORIGIN/../nvidia/nvjitlink/lib" - ) - endif() - - # When building the C++ libraries from source we must copy libraft.so alongside the - # pairwise_distance and random Cython libraries TODO: when we have a single 'compiled' raft - # library, we shouldn't need this - set(cython_lib_dir pylibraft) - install(TARGETS raft_lib DESTINATION ${cython_lib_dir}) -endif() - rapids_cython_init() add_subdirectory(pylibraft/common) add_subdirectory(pylibraft/random) add_subdirectory(pylibraft/sparse) - -if(DEFINED cython_lib_dir) - rapids_cython_add_rpath_entries(TARGET raft PATHS "${cython_lib_dir}") -endif() diff --git a/python/pylibraft/pylibraft/__init__.py b/python/pylibraft/pylibraft/__init__.py index b0869501f3..a01e02ec33 100644 --- a/python/pylibraft/pylibraft/__init__.py +++ b/python/pylibraft/pylibraft/__init__.py @@ -13,4 +13,15 @@ # limitations under the License. # +# If libraft 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 libraft +except ModuleNotFoundError: + pass +else: + libraft.load_library() + del libraft + from pylibraft._version import __git_commit__, __version__ diff --git a/python/pylibraft/pylibraft/common/CMakeLists.txt b/python/pylibraft/pylibraft/common/CMakeLists.txt index 53279bfaf7..d1c1acb3aa 100644 --- a/python/pylibraft/pylibraft/common/CMakeLists.txt +++ b/python/pylibraft/pylibraft/common/CMakeLists.txt @@ -20,5 +20,5 @@ set(linked_libraries raft::raft) rapids_cython_create_modules( CXX SOURCE_FILES "${cython_sources}" - LINKED_LIBRARIES "${linked_libraries}" ASSOCIATED_TARGETS raft MODULE_PREFIX common_ + LINKED_LIBRARIES "${linked_libraries}" MODULE_PREFIX common_ ) diff --git a/python/pylibraft/pylibraft/common/cuda.pxd b/python/pylibraft/pylibraft/common/cuda.pxd index a44d9aeb63..934573b51f 100644 --- a/python/pylibraft/pylibraft/common/cuda.pxd +++ b/python/pylibraft/pylibraft/common/cuda.pxd @@ -14,7 +14,7 @@ # limitations under the License. # -from cuda.ccudart cimport cudaStream_t +from cuda.bindings.cyruntime cimport cudaStream_t cdef class Stream: diff --git a/python/pylibraft/pylibraft/common/cuda.pyx b/python/pylibraft/pylibraft/common/cuda.pyx index c164a463ae..cda0fc7168 100644 --- a/python/pylibraft/pylibraft/common/cuda.pyx +++ b/python/pylibraft/pylibraft/common/cuda.pyx @@ -19,7 +19,7 @@ # cython: embedsignature = True # cython: language_level = 3 -from cuda.ccudart cimport ( +from cuda.bindings.cyruntime cimport ( cudaError_t, cudaGetErrorName, cudaGetErrorString, diff --git a/python/pylibraft/pylibraft/common/handle.pyx b/python/pylibraft/pylibraft/common/handle.pyx index d256e671bf..400b667789 100644 --- a/python/pylibraft/pylibraft/common/handle.pyx +++ b/python/pylibraft/pylibraft/common/handle.pyx @@ -21,7 +21,7 @@ import functools -from cuda.ccudart cimport cudaStream_t +from cuda.bindings.cyruntime cimport cudaStream_t from libc.stdint cimport uintptr_t from rmm.librmm.cuda_stream_view cimport ( diff --git a/python/pylibraft/pylibraft/common/interruptible.pyx b/python/pylibraft/pylibraft/common/interruptible.pyx index c489f2ee20..ceac387f58 100644 --- a/python/pylibraft/pylibraft/common/interruptible.pyx +++ b/python/pylibraft/pylibraft/common/interruptible.pyx @@ -22,7 +22,7 @@ import contextlib import signal -from cuda.ccudart cimport cudaStream_t +from cuda.bindings.cyruntime cimport cudaStream_t from cython.operator cimport dereference from rmm.librmm.cuda_stream_view cimport cuda_stream_view diff --git a/python/pylibraft/pylibraft/random/CMakeLists.txt b/python/pylibraft/pylibraft/random/CMakeLists.txt index 10ff776471..7d61855111 100644 --- a/python/pylibraft/pylibraft/random/CMakeLists.txt +++ b/python/pylibraft/pylibraft/random/CMakeLists.txt @@ -23,5 +23,5 @@ set(linked_libraries raft::raft raft::compiled) rapids_cython_create_modules( CXX SOURCE_FILES "${cython_sources}" - LINKED_LIBRARIES "${linked_libraries}" ASSOCIATED_TARGETS raft MODULE_PREFIX random_ + LINKED_LIBRARIES "${linked_libraries}" MODULE_PREFIX random_ ) diff --git a/python/pylibraft/pylibraft/sparse/linalg/CMakeLists.txt b/python/pylibraft/pylibraft/sparse/linalg/CMakeLists.txt index ef16981644..7b2c9f6162 100644 --- a/python/pylibraft/pylibraft/sparse/linalg/CMakeLists.txt +++ b/python/pylibraft/pylibraft/sparse/linalg/CMakeLists.txt @@ -23,5 +23,5 @@ set(linked_libraries raft::raft raft::compiled) rapids_cython_create_modules( CXX SOURCE_FILES "${cython_sources}" - LINKED_LIBRARIES "${linked_libraries}" ASSOCIATED_TARGETS raft MODULE_PREFIX sparse_ + LINKED_LIBRARIES "${linked_libraries}" MODULE_PREFIX sparse_ ) diff --git a/python/pylibraft/pylibraft/test/__init__py b/python/pylibraft/pylibraft/tests/__init__py similarity index 100% rename from python/pylibraft/pylibraft/test/__init__py rename to python/pylibraft/pylibraft/tests/__init__py diff --git a/python/pylibraft/pylibraft/test/pytest.ini b/python/pylibraft/pylibraft/tests/pytest.ini similarity index 100% rename from python/pylibraft/pylibraft/test/pytest.ini rename to python/pylibraft/pylibraft/tests/pytest.ini diff --git a/python/pylibraft/pylibraft/test/test_cai_wrapper.py b/python/pylibraft/pylibraft/tests/test_cai_wrapper.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_cai_wrapper.py rename to python/pylibraft/pylibraft/tests/test_cai_wrapper.py diff --git a/python/pylibraft/pylibraft/test/test_config.py b/python/pylibraft/pylibraft/tests/test_config.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_config.py rename to python/pylibraft/pylibraft/tests/test_config.py diff --git a/python/pylibraft/pylibraft/test/test_device_ndarray.py b/python/pylibraft/pylibraft/tests/test_device_ndarray.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_device_ndarray.py rename to python/pylibraft/pylibraft/tests/test_device_ndarray.py diff --git a/python/pylibraft/pylibraft/test/test_doctests.py b/python/pylibraft/pylibraft/tests/test_doctests.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_doctests.py rename to python/pylibraft/pylibraft/tests/test_doctests.py diff --git a/python/pylibraft/pylibraft/test/test_handle.py b/python/pylibraft/pylibraft/tests/test_handle.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_handle.py rename to python/pylibraft/pylibraft/tests/test_handle.py diff --git a/python/pylibraft/pylibraft/test/test_mdspan_serializer.py b/python/pylibraft/pylibraft/tests/test_mdspan_serializer.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_mdspan_serializer.py rename to python/pylibraft/pylibraft/tests/test_mdspan_serializer.py diff --git a/python/pylibraft/pylibraft/test/test_random.py b/python/pylibraft/pylibraft/tests/test_random.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_random.py rename to python/pylibraft/pylibraft/tests/test_random.py diff --git a/python/pylibraft/pylibraft/test/test_sparse.py b/python/pylibraft/pylibraft/tests/test_sparse.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_sparse.py rename to python/pylibraft/pylibraft/tests/test_sparse.py diff --git a/python/pylibraft/pylibraft/test/test_version.py b/python/pylibraft/pylibraft/tests/test_version.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_version.py rename to python/pylibraft/pylibraft/tests/test_version.py diff --git a/python/pylibraft/pylibraft/test/test_z_interruptible.py b/python/pylibraft/pylibraft/tests/test_z_interruptible.py similarity index 100% rename from python/pylibraft/pylibraft/test/test_z_interruptible.py rename to python/pylibraft/pylibraft/tests/test_z_interruptible.py diff --git a/python/pylibraft/pyproject.toml b/python/pylibraft/pyproject.toml index ba454af591..912f1ad947 100644 --- a/python/pylibraft/pyproject.toml +++ b/python/pylibraft/pyproject.toml @@ -32,11 +32,8 @@ license = { text = "Apache 2.0" } requires-python = ">=3.10" dependencies = [ "cuda-python", + "libraft==25.2.*,>=0.0.0a0", "numpy>=1.23,<3.0a0", - "nvidia-cublas", - "nvidia-curand", - "nvidia-cusolver", - "nvidia-cusparse", "rmm==25.2.*,>=0.0.0a0", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. classifiers = [ @@ -124,18 +121,22 @@ requires = [ "cmake>=3.26.4,!=3.30.0", "cuda-python", "cython>=3.0.0,<3.1.0a0", + "libraft==25.2.*,>=0.0.0a0", + "librmm==25.2.*,>=0.0.0a0", "ninja", "rmm==25.2.*,>=0.0.0a0", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. dependencies-file = "../../dependencies.yaml" -matrix-entry = "cuda_suffixed=true;use_cuda_wheels=true" +matrix-entry = "cuda_suffixed=true" [tool.pydistcheck] select = [ - # NOTE: size threshold is managed via CLI args in CI scripts "distro-too-large-compressed", ] +# PyPI limit is 100 MiB, fail CI before we get too close to that +max_allowed_size_compressed = '75M' + [tool.pytest.ini_options] filterwarnings = [ "error", diff --git a/python/raft-dask/CMakeLists.txt b/python/raft-dask/CMakeLists.txt index 9ebbaa5298..1fcb40a58d 100644 --- a/python/raft-dask/CMakeLists.txt +++ b/python/raft-dask/CMakeLists.txt @@ -25,38 +25,16 @@ project( LANGUAGES CXX CUDA ) -option(FIND_RAFT_CPP "Search for existing RAFT C++ installations before defaulting to local files" - OFF -) - rapids_cpm_init() # Once https://github.com/rapidsai/ucxx/issues/173 is resolved we can remove this. find_package(ucx REQUIRED) include(cmake/thirdparty/get_ucxx.cmake) -# If the user requested it we attempt to find RAFT. -if(FIND_RAFT_CPP) - find_package(raft "${RAPIDS_VERSION}" REQUIRED COMPONENTS distributed) -else() - set(raft_FOUND OFF) -endif() - -if(NOT raft_FOUND) - # raft-dask doesn't actually use raft libraries, it just needs the headers, so we can turn off all - # library compilation and we don't need to install anything here. - set(BUILD_TESTS OFF) - set(BUILD_PRIMS_BENCH OFF) - set(RAFT_COMPILE_LIBRARIES OFF) - set(RAFT_COMPILE_DIST_LIBRARY OFF) - set(RAFT_COMPILE_NN_LIBRARY OFF) - set(CUDA_STATIC_RUNTIME ON) - set(CUDA_STATIC_MATH_LIBRARIES ON) - set(RAFT_DASK_UCXX_STATIC ON) - - add_subdirectory(../../cpp raft-cpp EXCLUDE_FROM_ALL) - list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/cmake/find_modules) - find_package(NCCL REQUIRED) -endif() +# why these components: +# +# * 'raft' = the headers, needed to link against libraft +# * 'distributed' = needed for NCCL +find_package(raft "${RAPIDS_VERSION}" REQUIRED COMPONENTS raft distributed) include(rapids-cython-core) rapids_cython_init() diff --git a/python/raft-dask/cmake/thirdparty/get_ucxx.cmake b/python/raft-dask/cmake/thirdparty/get_ucxx.cmake index f5daf70f92..e6b9c4aa0e 100644 --- a/python/raft-dask/cmake/thirdparty/get_ucxx.cmake +++ b/python/raft-dask/cmake/thirdparty/get_ucxx.cmake @@ -45,8 +45,8 @@ function(find_and_configure_ucxx) endfunction() # Change pinned tag here to test a commit in CI -# To use a different RAFT locally, set the CMake variable -# CPM_raft_SOURCE=/path/to/local/raft +# To use a different ucxx locally, set the CMake variable +# CPM_ucxx_SOURCE=/path/to/local/ucxx find_and_configure_ucxx(VERSION 0.42 FORK rapidsai PINNED_TAG branch-0.42 diff --git a/python/raft-dask/pyproject.toml b/python/raft-dask/pyproject.toml index cabe8e72a6..d3a26db282 100644 --- a/python/raft-dask/pyproject.toml +++ b/python/raft-dask/pyproject.toml @@ -33,6 +33,7 @@ requires-python = ">=3.10" dependencies = [ "dask-cuda==25.2.*,>=0.0.0a0", "distributed-ucxx==0.42.*,>=0.0.0a0", + "libraft==25.2.*,>=0.0.0a0", "pylibraft==25.2.*,>=0.0.0a0", "rapids-dask-dependency==25.2.*,>=0.0.0a0", "ucx-py==0.42.*,>=0.0.0a0", @@ -119,6 +120,8 @@ build-backend = "scikit_build_core.build" requires = [ "cmake>=3.26.4,!=3.30.0", "cython>=3.0.0,<3.1.0a0", + "libraft==25.2.*,>=0.0.0a0", + "librmm==25.2.*,>=0.0.0a0", "libucx==1.15.0", "ninja", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. diff --git a/python/raft-dask/raft_dask/__init__.py b/python/raft-dask/raft_dask/__init__.py index 19a037ae75..78248fad7a 100644 --- a/python/raft-dask/raft_dask/__init__.py +++ b/python/raft-dask/raft_dask/__init__.py @@ -13,8 +13,6 @@ # limitations under the License. # -from raft_dask._version import __git_commit__, __version__ - # 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: @@ -24,3 +22,16 @@ else: libucx.load_library() del libucx + +# If libraft 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 libraft +except ModuleNotFoundError: + pass +else: + libraft.load_library() + del libraft + +from raft_dask._version import __git_commit__, __version__ diff --git a/python/raft-dask/raft_dask/common/CMakeLists.txt b/python/raft-dask/raft_dask/common/CMakeLists.txt index 65d5f06577..1279d5d501 100644 --- a/python/raft-dask/raft_dask/common/CMakeLists.txt +++ b/python/raft-dask/raft_dask/common/CMakeLists.txt @@ -15,6 +15,5 @@ set(cython_sources comms_utils.pyx nccl.pyx) set(linked_libraries raft::raft raft::distributed) rapids_cython_create_modules( - SOURCE_FILES "${cython_sources}" ASSOCIATED_TARGETS raft LINKED_LIBRARIES "${linked_libraries}" - CXX + SOURCE_FILES "${cython_sources}" LINKED_LIBRARIES "${linked_libraries}" CXX ) diff --git a/python/raft-dask/raft_dask/include_test/CMakeLists.txt b/python/raft-dask/raft_dask/include_test/CMakeLists.txt index 2ff1cd9150..8839c57b91 100644 --- a/python/raft-dask/raft_dask/include_test/CMakeLists.txt +++ b/python/raft-dask/raft_dask/include_test/CMakeLists.txt @@ -15,6 +15,5 @@ set(cython_sources raft_include_test.pyx) set(linked_libraries raft::raft) rapids_cython_create_modules( - SOURCE_FILES "${cython_sources}" ASSOCIATED_TARGETS raft LINKED_LIBRARIES "${linked_libraries}" - CXX + SOURCE_FILES "${cython_sources}" LINKED_LIBRARIES "${linked_libraries}" CXX ) diff --git a/python/raft-dask/raft_dask/test/conftest.py b/python/raft-dask/raft_dask/tests/conftest.py similarity index 100% rename from python/raft-dask/raft_dask/test/conftest.py rename to python/raft-dask/raft_dask/tests/conftest.py diff --git a/python/raft-dask/raft_dask/test/pytest.ini b/python/raft-dask/raft_dask/tests/pytest.ini similarity index 100% rename from python/raft-dask/raft_dask/test/pytest.ini rename to python/raft-dask/raft_dask/tests/pytest.ini diff --git a/python/raft-dask/raft_dask/test/test_comms.py b/python/raft-dask/raft_dask/tests/test_comms.py similarity index 100% rename from python/raft-dask/raft_dask/test/test_comms.py rename to python/raft-dask/raft_dask/tests/test_comms.py diff --git a/python/raft-dask/raft_dask/test/test_raft.py b/python/raft-dask/raft_dask/tests/test_raft.py similarity index 100% rename from python/raft-dask/raft_dask/test/test_raft.py rename to python/raft-dask/raft_dask/tests/test_raft.py diff --git a/python/raft-dask/raft_dask/test/test_version.py b/python/raft-dask/raft_dask/tests/test_version.py similarity index 100% rename from python/raft-dask/raft_dask/test/test_version.py rename to python/raft-dask/raft_dask/tests/test_version.py diff --git a/rapids_config.cmake b/rapids_config.cmake index c8077f7f4b..a40d7130c0 100644 --- a/rapids_config.cmake +++ b/rapids_config.cmake @@ -22,13 +22,15 @@ else() string(REPLACE "\n" "\n " _rapids_version_formatted " ${_rapids_version}") message( FATAL_ERROR - "Could not determine RAPIDS version. Contents of VERSION file:\n${_rapids_version_formatted}") + "Could not determine RAPIDS version. Contents of VERSION file:\n${_rapids_version_formatted}" + ) endif() if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/RAFT_RAPIDS-${RAPIDS_VERSION_MAJOR_MINOR}.cmake") file( DOWNLOAD "https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-${RAPIDS_VERSION_MAJOR_MINOR}/RAPIDS.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/RAFT_RAPIDS-${RAPIDS_VERSION_MAJOR_MINOR}.cmake") + "${CMAKE_CURRENT_BINARY_DIR}/RAFT_RAPIDS-${RAPIDS_VERSION_MAJOR_MINOR}.cmake" + ) endif() include("${CMAKE_CURRENT_BINARY_DIR}/RAFT_RAPIDS-${RAPIDS_VERSION_MAJOR_MINOR}.cmake")