diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0fd2023d..51198088 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -257,6 +257,7 @@ jobs: build_type: pull-request script: ci/test_wheel_pylibwholegraph.sh matrix_filter: map(select(.ARCH == "amd64")) + matrix_type: 'nightly' wheel-build-cugraph-pyg: needs: checks secrets: inherit @@ -279,3 +280,4 @@ jobs: build_type: pull-request script: ci/test_wheel_cugraph-pyg.sh matrix_filter: map(select(.ARCH == "amd64")) + matrix_type: 'nightly' diff --git a/.gitignore b/.gitignore index 1ccc2780..8d4f88e2 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,8 @@ wheels/ wheelhouse/ _skbuild/ cufile.log +*.tar.gz +*.whl ## Patching *.diff diff --git a/ci/download-torch-wheels.sh b/ci/download-torch-wheels.sh new file mode 100755 index 00000000..e6fbcaa9 --- /dev/null +++ b/ci/download-torch-wheels.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# [description] +# +# Downloads a CUDA variant of 'torch' from the correct index, based on CUDA major version. +# +# This exists to avoid using 'pip --extra-index-url', which could allow for CPU-only 'torch' +# to be downloaded from pypi.org. +# + +set -e -u -o pipefail + +TORCH_WHEEL_DIR="${1}" + +# Ensure CUDA-enabled 'torch' packages are always used. +# +# Downloading + passing the downloaded file as a requirement forces the use of this +# package, so we don't accidentally end up with a CPU-only 'torch' from 'pypi.org' +# (which can happen because pip doesn't support index priority). +rapids-dependency-file-generator \ + --output requirements \ + --file-key "torch_only" \ + --matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION};dependencies=${RAPIDS_DEPENDENCIES};include_torch_extra_index=false;require_gpu=true" \ +| tee "${PIP_CONSTRAINT}" + +rapids-pip-retry download \ + --isolated \ + --prefer-binary \ + --no-deps \ + -d "${TORCH_WHEEL_DIR}" \ + --constraint "${PIP_CONSTRAINT}" \ + 'torch' diff --git a/ci/test_wheel_cugraph-pyg.sh b/ci/test_wheel_cugraph-pyg.sh index c05e18af..765e7723 100755 --- a/ci/test_wheel_cugraph-pyg.sh +++ b/ci/test_wheel_cugraph-pyg.sh @@ -15,13 +15,16 @@ LIBWHOLEGRAPH_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libwholegraph_${RAPIDS_PY_CUDA_ PYLIBWHOLEGRAPH_WHEELHOUSE=$(rapids-download-from-github "$(rapids-package-name "wheel_python" pylibwholegraph --stable --cuda "$RAPIDS_CUDA_VERSION")") CUGRAPH_PYG_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="${package_name}_${RAPIDS_PY_CUDA_SUFFIX}" RAPIDS_PY_WHEEL_PURE="1" rapids-download-wheels-from-github python) -CUDA_MAJOR="${RAPIDS_CUDA_VERSION%%.*}" +# generate constraints, accounting for 'oldest' and 'latest' dependencies +rapids-dependency-file-generator \ + --output requirements \ + --file-key "test_cugraph_pyg" \ + --matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION};dependencies=${RAPIDS_DEPENDENCIES};include_torch_extra_index=false" \ +| tee "${PIP_CONSTRAINT}" -if [[ "${CUDA_MAJOR}" == "12" ]]; then - PYTORCH_INDEX="https://download.pytorch.org/whl/cu126" -else - PYTORCH_INDEX="https://download.pytorch.org/whl/cu130" -fi +# ensure a CUDA variant of 'torch' is used +TORCH_WHEEL_DIR="$(mktemp -d)" +./ci/download-torch-wheels.sh "${TORCH_WHEEL_DIR}" # notes: # @@ -30,12 +33,13 @@ fi # its dependencies are available from pypi.org # rapids-pip-retry install \ - -v \ - --extra-index-url "${PYTORCH_INDEX}" \ + --prefer-binary \ + --constraint "${PIP_CONSTRAINT}" \ --extra-index-url 'https://pypi.nvidia.com' \ "${LIBWHOLEGRAPH_WHEELHOUSE}"/*.whl \ "$(echo "${PYLIBWHOLEGRAPH_WHEELHOUSE}"/pylibwholegraph_"${RAPIDS_PY_CUDA_SUFFIX}"*.whl)" \ - "$(echo "${CUGRAPH_PYG_WHEELHOUSE}"/cugraph_pyg_"${RAPIDS_PY_CUDA_SUFFIX}"*.whl)[test]" + "$(echo "${CUGRAPH_PYG_WHEELHOUSE}"/cugraph_pyg_"${RAPIDS_PY_CUDA_SUFFIX}"*.whl)[test]" \ + "${TORCH_WHEEL_DIR}"/torch-*.whl # RAPIDS_DATASET_ROOT_DIR is used by test scripts export RAPIDS_DATASET_ROOT_DIR="$(realpath datasets)" diff --git a/ci/test_wheel_pylibwholegraph.sh b/ci/test_wheel_pylibwholegraph.sh index 252c6cfa..5aae7cd3 100755 --- a/ci/test_wheel_pylibwholegraph.sh +++ b/ci/test_wheel_pylibwholegraph.sh @@ -2,9 +2,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION. # SPDX-License-Identifier: Apache-2.0 -set -e # abort the script on error -set -o pipefail # piped commands propagate their error -set -E # ERR traps are inherited by subcommands +set -euo pipefail # Delete system libnccl.so to ensure the wheel is used. # (but only do this in CI, to avoid breaking local dev environments) @@ -18,23 +16,29 @@ RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen ${RAPIDS_CUDA_VERSION})" LIBWHOLEGRAPH_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libwholegraph_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github cpp) PYLIBWHOLEGRAPH_WHEELHOUSE=$(rapids-download-from-github "$(rapids-package-name "wheel_python" pylibwholegraph --stable --cuda "$RAPIDS_CUDA_VERSION")") -# determine pytorch source -if [[ "${CUDA_MAJOR}" == "12" ]]; then - PYTORCH_INDEX="https://download.pytorch.org/whl/cu126" -else - PYTORCH_INDEX="https://download.pytorch.org/whl/cu130" -fi RAPIDS_TESTS_DIR=${RAPIDS_TESTS_DIR:-"${PWD}/test-results"} RAPIDS_COVERAGE_DIR=${RAPIDS_COVERAGE_DIR:-"${PWD}/coverage-results"} mkdir -p "${RAPIDS_TESTS_DIR}" "${RAPIDS_COVERAGE_DIR}" +# generate constraints, accounting for 'oldest' and 'latest' dependencies +rapids-dependency-file-generator \ + --output requirements \ + --file-key "test_pylibwholegraph" \ + --matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch);py=${RAPIDS_PY_VERSION};dependencies=${RAPIDS_DEPENDENCIES};include_torch_extra_index=false" \ +| tee "${PIP_CONSTRAINT}" + +# ensure a CUDA variant of 'torch' is used +TORCH_WHEEL_DIR="$(mktemp -d)" +./ci/download-torch-wheels.sh "${TORCH_WHEEL_DIR}" + # echo to expand wildcard before adding `[extra]` requires for pip rapids-logger "Installing Packages" rapids-pip-retry install \ - --extra-index-url ${PYTORCH_INDEX} \ + --prefer-binary \ + --constraint "${PIP_CONSTRAINT}" \ "$(echo "${PYLIBWHOLEGRAPH_WHEELHOUSE}"/pylibwholegraph*.whl)[test]" \ "${LIBWHOLEGRAPH_WHEELHOUSE}"/*.whl \ - 'torch>=2.3' + "${TORCH_WHEEL_DIR}"/torch-*.whl rapids-logger "pytest pylibwholegraph" cd python/pylibwholegraph/pylibwholegraph/tests diff --git a/conda/recipes/cugraph-pyg/recipe.yaml b/conda/recipes/cugraph-pyg/recipe.yaml index 3243a6c8..e1556273 100644 --- a/conda/recipes/cugraph-pyg/recipe.yaml +++ b/conda/recipes/cugraph-pyg/recipe.yaml @@ -40,7 +40,7 @@ requirements: # This is intentionally spelled 'pytorch' (not 'pytorch-gpu' and not using build string selectors) # because we want it to be possible to at least install `cugraph-pyg` in an environment without a GPU, # to support use cases like building container images. - - pytorch >=2.3 + - pytorch >=2.4 - pytorch_geometric >=2.5,<2.8 tests: diff --git a/dependencies.yaml b/dependencies.yaml index bfd0d5e0..ec821aa7 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -60,12 +60,11 @@ files: - depends_on_cudf - depends_on_pytorch - depends_on_cuml - - depends_on_ogb - - depends_on_sentence_transformers - py_version - test_python_common - depends_on_pylibwholegraph - depends_on_cugraph_pyg + - test_python_cugraph_pyg test_pylibwholegraph: output: none includes: @@ -76,6 +75,10 @@ files: - test_python_common - depends_on_pylibwholegraph - test_python_pylibwholegraph + torch_only: + output: none + includes: + - depends_on_pytorch py_build_libwholegraph: output: pyproject pyproject_dir: python/libwholegraph @@ -135,6 +138,7 @@ files: table: project.optional-dependencies key: test includes: + - depends_on_pytorch - test_python_common - test_python_pylibwholegraph py_build_cugraph_pyg: @@ -324,6 +328,10 @@ dependencies: - *cmake_ver test_python_common: common: + - output_types: [conda] + packages: + - torchdata + - pydantic - output_types: [conda, pyproject, requirements] packages: - pytest<9.0.0 @@ -335,6 +343,7 @@ dependencies: - output_types: [conda, pyproject, requirements] packages: - ogb + # for MovieLens example - sentence-transformers test_python_pylibwholegraph: common: @@ -343,30 +352,53 @@ dependencies: - pytest-forked - scipy depends_on_pytorch: - common: - - output_types: [conda] - packages: - - torchdata - - pydantic specific: - output_types: [requirements] matrices: + # If 'include_torch_extra_index=false' is passed, avoid these --extra-index-url. + # (useful in CI scripts where we want to tightly control which indices 'pip' uses). - matrix: - cuda: "12.*" + include_torch_extra_index: "false" + packages: + # otherwise, choose a CUDA-version-specific index + - matrix: + cuda: "12.[234]" packages: + # oldest torch: 2.4.0+cu124 + - &oldest_torch_index_cu12 --extra-index-url=https://download.pytorch.org/whl/cu124 + - matrix: + cuda: "12.[56]" + packages: + # oldest torch: 2.6.0+cu126 - --extra-index-url=https://download.pytorch.org/whl/cu126 + - matrix: + cuda: "12.[78]" + packages: + # oldest torch: 2.7.0+cu128 + - --extra-index-url=https://download.pytorch.org/whl/cu128 + - matrix: + cuda: "12.*" + packages: + # oldest torch: 2.8.0+cu129 + - &latest_torch_index_cu12 --extra-index-url=https://download.pytorch.org/whl/cu129 - matrix: cuda: "13.*" packages: - - --extra-index-url=https://download.pytorch.org/whl/cu130 + # oldest torch: 2.9.0+cu130 + - &torch_index_cu13 --extra-index-url=https://download.pytorch.org/whl/cu130 - matrix: packages: + # For pyproject.toml (and therefore wheel metadata), avoid --extra-index-url + # and use pins that don't have CUDA-specific version modifiers (so installing alongside + # CPU-only torch is technically possible). + # + # --extra-index-url for requirements is handled by other lists here. - output_types: [requirements, pyproject] matrices: - matrix: cuda: "12.*" packages: - - torch>=2.3 + - torch>=2.4 - matrix: cuda: "13.*" packages: @@ -374,14 +406,52 @@ dependencies: - matrix: packages: - *pytorch_pip + # For [requirements], include --extra-index-url and CUDA-specific version modifiers + # to ensure we get CUDA builds at test time. + - output_types: [requirements] + matrices: + - matrix: + cuda: "12.*" + dependencies: "oldest" + require_gpu: "true" + packages: + - *oldest_torch_index_cu12 + - torch==2.4.0+cu124 + - matrix: + cuda: "13.*" + dependencies: "oldest" + require_gpu: "true" + packages: + - *torch_index_cu13 + - torch==2.9.0+cu130 + - matrix: + cuda: "12.*" + require_gpu: "true" + packages: + - *latest_torch_index_cu12 + - torch==2.8.0+cu129 + - matrix: + cuda: "13.*" + require_gpu: "true" + packages: + - *torch_index_cu13 + - torch==2.10.0+cu130 + # Nothing above matches, don't add a CUDA-specific 'torch' requirement. + # + # This keeps these tight pins out of [test] extras in wheels. + # + # Also useful for cases like RAPIDS DLFW builds, where 'torch' is provided a different + # way and we want to avoid installing it from external repos. + - matrix: + packages: - output_types: [conda] matrices: # Prevent fallback to CPU-only pytorch when we want a CUDA variant. - matrix: require_gpu: "true" packages: - - pytorch-gpu - # Default to falling back to whatever 'pytorch' is pulled in via cugraph-pyg's dependencies. + - pytorch-gpu >=2.4 + # Default to falling back to whatever 'pytorch' is pulled in via cugraph-pyg's / pylibwholegraph's dependencies. - matrix: packages: depends_on_nccl: @@ -399,17 +469,6 @@ dependencies: - nvidia-nccl-cu12>=2.19 - matrix: packages: - depends_on_ogb: - common: - - output_types: [conda, requirements, pyproject] - packages: - - ogb - # for MovieLens example - depends_on_sentence_transformers: - common: - - output_types: [conda, requirements, pyproject] - packages: - - sentence-transformers depends_on_pyg: common: - output_types: [conda] diff --git a/python/pylibwholegraph/pyproject.toml b/python/pylibwholegraph/pyproject.toml index be659b68..4eb52885 100644 --- a/python/pylibwholegraph/pyproject.toml +++ b/python/pylibwholegraph/pyproject.toml @@ -39,6 +39,7 @@ test = [ "pytest-xdist", "pytest<9.0.0", "scipy", + "torch>=2.9.0", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`. [tool.rapids-build-backend]