From a2e967c43f7ed3e27107c7e32a5d2240b480bf7f Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 11:41:55 +0800 Subject: [PATCH 01/28] [WIP] Migrate to CTK13 as the default for Linux. --- .github/workflows/main.yml | 89 ++++++++++--------- doc/contrib/ci.rst | 11 +-- doc/install.rst | 29 ++++-- ops/conda_env/aarch64_test.yml | 33 ------- ops/conda_env/linux_cpu_test.yml | 40 --------- ops/pipeline/audit-cuda-wheel.sh | 13 ++- ops/pipeline/build-cpu.sh | 1 - ops/pipeline/build-cuda.sh | 27 +++--- .../build-python-wheels-arm64-impl.sh | 32 ------- ops/pipeline/build-variant-wheels-impl.sh | 4 +- ops/pipeline/build-variant-wheels.sh | 6 +- ops/pipeline/get-image-tag.sh | 2 +- ops/pipeline/nightly-test-cccl.sh | 2 +- ops/pipeline/nightly-test-rmm.sh | 2 +- ops/pipeline/test-python-wheel.sh | 9 +- ops/script/change_version.py | 2 +- ops/script/release_artifacts.py | 12 +-- python-package/pyproject.toml | 4 +- 18 files changed, 120 insertions(+), 198 deletions(-) delete mode 100644 ops/conda_env/aarch64_test.yml delete mode 100644 ops/conda_env/linux_cpu_test.yml delete mode 100755 ops/pipeline/build-python-wheels-arm64-impl.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 36fe88dddf91..16157fa09098 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,8 +70,12 @@ jobs: - uses: dmlc/xgboost-devops/actions/sccache@main with: cache-key-prefix: ${{ github.job }}-${{ matrix.build_suite }} - - name: Build and test - run: bash ops/pipeline/build-cpu.sh ${{ matrix.build_suite }} + - name: Build run C++ tests on CPU + if: matrix.variant == 'default' + shell: bash -l {0} + run: | + source activate linux_cpu_test + bash ops/pipeline/build-cpu.sh ${{ matrix.build_suite }} - name: Test federated learning on CPU if: matrix.variant == 'default' shell: bash -l {0} @@ -81,6 +85,9 @@ jobs: cd python-package && pip install -e . --no-deps --no-build-isolation && cd - timeout 600s pytest -v -s -rxXs --durations=0 tests/test_distributed/test_federated - run: sccache --show-stats + - name: Build and test with sanitizer + if: matrix.variant == 'sanitizer' + run: bash ops/pipeline/build-cpu.sh ${{ matrix.build_suite }} build-cuda: name: Build CUDA ${{ matrix.cuda_version }} (${{ matrix.arch }}) @@ -94,27 +101,27 @@ jobs: fail-fast: false matrix: include: - # CUDA 12 + # xgboost-cu12 - cuda_version: 12 arch: aarch64 runner: linux-arm64-cpu - image_repo: xgb-ci.gpu_build_rockylinux8_aarch64 + image_repo: xgb-ci.gpu_build_cuda12_rockylinux8_aarch64 use_rmm: 0 - cuda_version: 12 arch: x86_64 runner: linux-amd64-cpu - image_repo: xgb-ci.gpu_build_rockylinux8 + image_repo: xgb-ci.gpu_build_cuda12_rockylinux8 use_rmm: 0 - # CUDA 13 + # Default xgboost package (CUDA 13) - cuda_version: 13 arch: aarch64 runner: linux-arm64-cpu - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8_aarch64 + image_repo: xgb-ci.gpu_build_rockylinux8_aarch64 use_rmm: 0 - cuda_version: 13 arch: x86_64 runner: linux-amd64-cpu - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8 + image_repo: xgb-ci.gpu_build_rockylinux8 use_rmm: 0 container: image: ${{ needs.ci-configure.outputs.docker_registry }}/${{ matrix.image_repo }}:${{ needs.ci-configure.outputs.image_tag }} @@ -161,7 +168,7 @@ jobs: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main with: - cache-key-prefix: ${{ github.job }}-clang21-cuda12 + cache-key-prefix: ${{ github.job }}-clang21-cuda13 - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 21.1.8 - run: sccache --show-stats @@ -176,22 +183,22 @@ jobs: fail-fast: false matrix: include: - # CUDA 12 + # xgboost-cu12 - cuda_version: 12 - cuda_variant_flag: "" + cuda_variant_flag: "--cuda-variant cuda12" arch: aarch64 runner: linux-arm64-cpu - cuda_version: 12 - cuda_variant_flag: "" + cuda_variant_flag: "--cuda-variant cuda12" arch: x86_64 runner: linux-amd64-cpu - # CUDA 13 + # Default xgboost package (CUDA 13) - cuda_version: 13 - cuda_variant_flag: "--cuda-variant cuda13" + cuda_variant_flag: "" arch: aarch64 runner: linux-arm64-cpu - cuda_version: 13 - cuda_variant_flag: "--cuda-variant cuda13" + cuda_variant_flag: "" arch: x86_64 runner: linux-amd64-cpu container: @@ -225,7 +232,7 @@ jobs: python-package/dist/*.whl build-cuda-with-rmm: - name: Build CUDA with RMM + name: Build CUDA 13 with RMM needs: ci-configure runs-on: - runs-on=${{ github.run_id }} @@ -243,9 +250,11 @@ jobs: with: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main + with: + cache-key-prefix: ${{ github.job }}-cuda13 - run: >- bash ops/pipeline/build-cuda.sh - --cuda-version 12 + --cuda-version 13 --use-rmm 1 - run: sccache --show-stats - name: Stash files @@ -331,7 +340,7 @@ jobs: fail-fast: false matrix: include: - # CUDA 12 tests + # CUDA 12 artifact compatibility tests (using the default CUDA 13 runtime) # Note: --gpus all provides GPU access; --privileged is not needed for basic GPU tests - cuda_version: 12 suite: gpu @@ -349,14 +358,6 @@ jobs: artifact_from: build-cuda12-aarch64 container_options: "--gpus all --privileged" test_args: "" - - cuda_version: 12 - suite: gpu-rmm - arch: x86_64 - runner: linux-amd64-gpu - image_repo: xgb-ci.gpu - artifact_from: build-cuda-with-rmm - container_options: "--gpus all --privileged" - test_args: "--use-rmm-pool --gtest_filter=-*DeathTest*" - cuda_version: 12 suite: mgpu arch: x86_64 @@ -366,12 +367,12 @@ jobs: # mgpu needs --shm-size for NCCL shared memory communication container_options: "--gpus all --shm-size=4g --privileged" test_args: "--gtest_filter=*MGPU*" - # CUDA 13 tests + # Default CUDA 13 artifact tests - cuda_version: 13 suite: gpu arch: x86_64 runner: linux-amd64-gpu - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8 + image_repo: xgb-ci.gpu artifact_from: build-cuda13-x86_64 container_options: "--gpus all --privileged" test_args: "" @@ -379,10 +380,18 @@ jobs: suite: gpu arch: aarch64 runner: linux-arm64-gpu - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8_aarch64 + image_repo: xgb-ci.gpu_aarch64 artifact_from: build-cuda13-aarch64 container_options: "--gpus all --privileged" test_args: "" + - cuda_version: 13 + suite: gpu-rmm + arch: x86_64 + runner: linux-amd64-gpu + image_repo: xgb-ci.gpu + artifact_from: build-cuda-with-rmm + container_options: "--gpus all --privileged" + test_args: "--use-rmm-pool --gtest_filter=-*DeathTest*" container: image: ${{ needs.ci-configure.outputs.docker_registry }}/${{ matrix.image_repo }}:${{ needs.ci-configure.outputs.image_tag }} credentials: @@ -416,7 +425,7 @@ jobs: fail-fast: false matrix: include: - # CUDA 12 tests + # xgboost-cu12 tests (using the default CUDA 13 runtime) - cuda_version: 12 description: GPU-x86_64-CUDA-12 image_repo: xgb-ci.gpu @@ -432,7 +441,7 @@ jobs: artifact_from: audit-cuda12-wheel-x86_64 # mgpu needs --shm-size for NCCL shared memory communication container_options: "--gpus all --shm-size=4g --privileged" - # CUDA 12 aarch64 tests + # xgboost-cu12 aarch64 test (using the default CUDA 13 runtime) - cuda_version: 12 description: GPU-arm64-CUDA-12 image_repo: xgb-ci.gpu_aarch64 @@ -440,17 +449,17 @@ jobs: runner: linux-arm64-gpu artifact_from: audit-cuda12-wheel-aarch64 container_options: "--gpus all --privileged" - # CUDA 13 tests + # Default xgboost package tests (CUDA 13) - cuda_version: 13 description: GPU-x86_64-CUDA-13 - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8 + image_repo: xgb-ci.gpu suite: gpu runner: linux-amd64-gpu artifact_from: audit-cuda13-wheel-x86_64 container_options: "--gpus all --privileged" - cuda_version: 13 description: GPU-arm64-CUDA-13 - image_repo: xgb-ci.gpu_build_cuda13_rockylinux8_aarch64 + image_repo: xgb-ci.gpu_aarch64 suite: gpu-arm64 runner: linux-arm64-gpu artifact_from: audit-cuda13-wheel-aarch64 @@ -476,16 +485,16 @@ jobs: bash ops/pipeline/test-python-wheel.sh --suite ${{ matrix.suite }} --cuda-version ${{ matrix.cuda_version }} - # Train a model for cross-platform testing (only for CUDA 12 x86_64) + # Train a model for cross-platform testing (only for default CUDA 13 x86_64) - name: Train cross-platform test model - if: matrix.cuda_version == 12 && matrix.suite == 'gpu' + if: matrix.cuda_version == 13 && matrix.suite == 'gpu' shell: bash -l {0} run: | source activate gpu_test python tests/cross-platform/test_cross_platform_model.py \ --train --model-path cross_platform_model.ubj - name: Upload cross-platform model artifact - if: matrix.cuda_version == 12 && matrix.suite == 'gpu' + if: matrix.cuda_version == 13 && matrix.suite == 'gpu' uses: actions/upload-artifact@v7.0.1 with: name: cross-platform-model @@ -505,20 +514,20 @@ jobs: timeout-minutes: 60 strategy: fail-fast: false - # Uses the wheel from cuda12 for tests. + # Uses the default CUDA 13 wheel for tests. matrix: include: - description: CPU-amd64 image_repo: xgb-ci.cpu suite: cpu runner: linux-amd64-cpu - artifact_from: audit-cuda12-wheel-x86_64 + artifact_from: audit-cuda13-wheel-x86_64 container_options: "--init" - description: CPU-arm64 image_repo: xgb-ci.cpu_aarch64 suite: cpu-arm64 runner: linux-arm64-cpu - artifact_from: audit-cuda12-wheel-aarch64 + artifact_from: audit-cuda13-wheel-aarch64 container_options: "--init" container: image: ${{ needs.ci-configure.outputs.docker_registry }}/${{ matrix.image_repo }}:${{ needs.ci-configure.outputs.image_tag }} diff --git a/doc/contrib/ci.rst b/doc/contrib/ci.rst index 1d96ea49adc7..76d055fb68ef 100644 --- a/doc/contrib/ci.rst +++ b/doc/contrib/ci.rst @@ -117,9 +117,10 @@ YAML file ``containers/ci_container.yml``. For example, when ``IMAGE_REPO`` is s xgb-ci.gpu: container_def: gpu build_args: - CUDA_VERSION_ARG: "12.4.1" - NCCL_VERSION_ARG: "2.23.4-1" - RAPIDS_VERSION_ARG: "24.10" + CUDA_VERSION: "13.3.0" + NCCL_VERSION: "2.30.7-1" + RAPIDS_VERSION: "26.04" + ARCH: x86_64 The ``container_def`` entry indicates where the Dockerfile is located. The container definition will be fetched from ``containers/dockerfile/Dockerfile.CONTAINER_DEF`` where @@ -131,8 +132,8 @@ the build arguments are: .. code-block:: - --build-arg CUDA_VERSION_ARG=12.4.1 --build-arg NCCL_VERSION_ARG=2.23.4-1 \ - --build-arg RAPIDS_VERSION_ARG=24.10 + --build-arg CUDA_VERSION=13.3.0 --build-arg NCCL_VERSION=2.30.7-1 \ + --build-arg RAPIDS_VERSION=26.04 --build-arg ARCH=x86_64 The build arguments provide inputs to the ``ARG`` instructions in the Dockerfile. diff --git a/doc/install.rst b/doc/install.rst index 1239e7c2e59c..128759150310 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -31,7 +31,7 @@ into permission errors. Starting from 2.1.0, XGBoost Python package will be distributed in two variants: - * ``manylinux_2_28``: for recent Linux distros with glibc 2.28 or newer. This variant comes with all features enabled. + * ``manylinux_2_28``: for recent Linux distros with glibc 2.28 or newer. This variant supports GPU algorithms. * ``manylinux2014``: for old Linux distros with glibc older than 2.28. This variant does not support GPU algorithms or federated learning. The ``pip`` package manager will automatically choose the correct variant depending on your system. @@ -41,8 +41,7 @@ into permission errors. depend on software components that reached end-of-life (such as CentOS 7). We strongly encourage everyone to migrate to recent Linux distros in order to use future versions of XGBoost. - Note. If you want to use GPU algorithms or federated learning on an older Linux distro, you have - two alternatives: + Note. If you want to use GPU algorithms on an older Linux distro, you have two alternatives: 1. Upgrade to a recent Linux distro with glibc 2.28+. OR 2. Build XGBoost from the source. @@ -57,6 +56,10 @@ into permission errors. Redistributable. +.. note:: + + Federated learning has been removed from PyPI binary wheels since 3.4 + Capabilities of binary wheels for each platform: .. |tick| unicode:: U+2714 @@ -81,9 +84,24 @@ modern Jetson or Graviton machines provides the same GPU functionality as the Linux x86_64 wheel. Multi-node and multi-GPU training remain experimental on ARM64 at this time. +CUDA toolkit variants (Linux) +***************************** +The default ``xgboost`` wheel for Linux x86_64 and aarch64 is built with CUDA Toolkit 13.x: + +.. code-block:: bash + + pip install xgboost + +Users whose NVIDIA driver or GPU supports CUDA 12 but not CUDA 13 can instead install the full CUDA 12 package: + +.. code-block:: bash + + pip install xgboost-cu12 + + Minimal installation (CPU-only) ******************************* -The default installation with ``pip`` will install the full XGBoost package, including the support for the GPU algorithms and federated learning. +The default installation with ``pip`` will install the full XGBoost package, including support for GPU algorithms. You may choose to reduce the size of the installed package and save the disk space, by opting to install ``xgboost-cpu`` instead: @@ -91,8 +109,7 @@ You may choose to reduce the size of the installed package and save the disk spa pip install xgboost-cpu -The ``xgboost-cpu`` variant will have drastically smaller disk footprint, but does not provide some features, such as the GPU algorithms and -federated learning. +The ``xgboost-cpu`` variant has a drastically smaller disk footprint, but does not provide GPU algorithms. Conda ***** diff --git a/ops/conda_env/aarch64_test.yml b/ops/conda_env/aarch64_test.yml deleted file mode 100644 index fd26e3cd18c1..000000000000 --- a/ops/conda_env/aarch64_test.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: aarch64_test -channels: -- conda-forge -dependencies: -- python=3.12 -- pip -- wheel -- pytest -- pytest-cov -- numpy -- scipy -- scikit-learn -- pandas -- matplotlib -- dask -- distributed -- hypothesis -- graphviz -- python-graphviz -- codecov -- cmake -- ninja -- boto3 -- awscli -- numba -- llvmlite -- loky>=3.5.1 -- pyarrow -- pyspark>=4.0.0 -- cloudpickle -- pip: - - awscli - - auditwheel diff --git a/ops/conda_env/linux_cpu_test.yml b/ops/conda_env/linux_cpu_test.yml deleted file mode 100644 index 1d0b2f29d2b4..000000000000 --- a/ops/conda_env/linux_cpu_test.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: linux_cpu_test -channels: -- conda-forge -dependencies: -- python=3.12 -- cmake>=3.26.4 -- c-compiler -- cxx-compiler -- ninja -- pip -- wheel -- pyyaml -- cpplint -- pylint -- numpy -- scipy -- scikit-learn>=1.4.1 -- pandas -- polars -- matplotlib -- dask<=2024.10.0 -- distributed<=2024.10.0 -- python-graphviz -- hypothesis>=6.46 -- astroid -- sh -- mock -- pytest -- pytest-timeout -- pytest-cov -- python-kubernetes -- urllib3 -- boto3 -- awscli -- py-ubjson -- loky>=3.5.1 -- pyarrow -- cloudpickle -- modin -- pyspark>=4.0.0 diff --git a/ops/pipeline/audit-cuda-wheel.sh b/ops/pipeline/audit-cuda-wheel.sh index de5e396e6afd..644a5fe67cba 100755 --- a/ops/pipeline/audit-cuda-wheel.sh +++ b/ops/pipeline/audit-cuda-wheel.sh @@ -12,7 +12,7 @@ fi if [[ "$#" -lt 1 ]] then - echo "Usage: $0 {x86_64,aarch64} [--cuda-variant {cuda,cuda13}]" + echo "Usage: $0 {x86_64,aarch64} [--cuda-variant {cuda,cuda12}]" exit 2 fi arch="$1" @@ -33,6 +33,15 @@ while [[ $# -gt 0 ]]; do esac done +case "${cuda_variant}" in + cuda|cuda12) + ;; + *) + echo "Invalid CUDA variant: ${cuda_variant}. Expected cuda or cuda12." + exit 2 + ;; +esac + source ops/pipeline/classify-git-branch.sh WHEEL_TAG=manylinux_2_28_${arch} @@ -64,7 +73,7 @@ fi # Check size of wheel pydistcheck --config python-package/pyproject.toml "${final_wheel}" -# Generate meta.json only for the main CUDA variant (not cuda13) +# Generate meta.json only for the default CUDA variant (not cuda12) if [[ $cuda_variant == "cuda" && $arch == "x86_64" ]] then # Generate the meta info which includes xgboost version and the commit info diff --git a/ops/pipeline/build-cpu.sh b/ops/pipeline/build-cpu.sh index 24e9bb2b3ef3..50b520887b03 100755 --- a/ops/pipeline/build-cpu.sh +++ b/ops/pipeline/build-cpu.sh @@ -25,7 +25,6 @@ case "${suite}" in -DCMAKE_C_COMPILER_LAUNCHER=sccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ -DCMAKE_COMPILE_WARNING_AS_ERROR=OFF \ - -DCMAKE_PREFIX_PATH='/opt/grpc' \ -DPLUGIN_FEDERATED=ON time ninja -v echo "--- Run Google Test" diff --git a/ops/pipeline/build-cuda.sh b/ops/pipeline/build-cuda.sh index a71ab41694da..15a64664abee 100755 --- a/ops/pipeline/build-cuda.sh +++ b/ops/pipeline/build-cuda.sh @@ -8,14 +8,14 @@ ## All parameters are required (no defaults). ## ## Examples: -## # CUDA 12 standard build +## # CUDA 12 xgboost-cu12 package build ## build-cuda.sh --cuda-version 12 --use-rmm 0 ## -## # CUDA 12 with RMM -## build-cuda.sh --cuda-version 12 --use-rmm 1 -## -## # CUDA 13 +## # Default CUDA 13 build ## build-cuda.sh --cuda-version 13 --use-rmm 0 +## +## # CUDA 13 with RMM +## build-cuda.sh --cuda-version 13 --use-rmm 1 set -euo pipefail @@ -72,12 +72,9 @@ case "${use_rmm}" in ;; esac -# Validate CUDA 13 constraints -if [[ "${cuda_version}" == "13" ]]; then - if [[ "${use_rmm}" == "1" ]]; then - echo "Error: RMM is not supported for CUDA 13 (--use-rmm must be 0)" - exit 1 - fi +if [[ "${cuda_version}" == "12" && "${use_rmm}" == "1" ]]; then + echo "Error: CUDA 12 is reserved for the xgboost-cu12 package build and does not support RMM" + exit 1 fi # Export validated values @@ -95,9 +92,11 @@ fi set -x -# Configure PyPI variant for CUDA 13 -if [[ "${cuda_version}" == "13" ]]; then - python3 ops/script/pypi_variants.py --use-suffix=cu13 --require-nccl-dep=cu13 +# Configure the PyPI package variant +if [[ "${cuda_version}" == "12" ]]; then + python3 ops/script/pypi_variants.py --use-suffix=cu12 --require-nccl-dep=cu12 +else + python3 ops/script/pypi_variants.py --use-suffix=na --require-nccl-dep=cu13 fi # Run the build implementation directly (we're already inside the container) diff --git a/ops/pipeline/build-python-wheels-arm64-impl.sh b/ops/pipeline/build-python-wheels-arm64-impl.sh deleted file mode 100755 index 263df67f1bd2..000000000000 --- a/ops/pipeline/build-python-wheels-arm64-impl.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -## Build and test XGBoost with ARM64 CPU -## Companion script for ops/pipeline/build-cpu-arm64.sh - -set -euox pipefail - -source activate aarch64_test - -echo "--- Build libxgboost from the source" -mkdir -p build -pushd build - -cmake .. \ - -GNinja \ - -DCMAKE_PREFIX_PATH="${CONDA_PREFIX}" \ - -DUSE_OPENMP=ON \ - -DHIDE_CXX_SYMBOLS=ON \ - -DGOOGLE_TEST=ON \ - -DUSE_DMLC_GTEST=ON \ - -DENABLE_ALL_WARNINGS=ON \ - -DCMAKE_COMPILE_WARNING_AS_ERROR=OFF -time ninja -v - -echo "--- Run Google Test" -ctest --extra-verbose -popd - -echo "--- Build binary wheel" -pushd python-package -rm -rfv dist/* -pip wheel --no-deps -v . --wheel-dir dist/ -popd diff --git a/ops/pipeline/build-variant-wheels-impl.sh b/ops/pipeline/build-variant-wheels-impl.sh index b033fc2f8571..11b6237ae5a1 100755 --- a/ops/pipeline/build-variant-wheels-impl.sh +++ b/ops/pipeline/build-variant-wheels-impl.sh @@ -19,6 +19,6 @@ set -xu python -m pip install "variantlib[cli] @ git+https://github.com/wheelnext/variantlib.git@main" python -m pip install "nvidia-variant-provider @ git+https://github.com/wheelnext/nvidia-variant-provider.git@master" variantlib make-variant --no-isolation -f python-package/dist/xgboost-*.whl \ - -p "nvidia :: cuda_version_lower_bound :: 12.0" \ - -p "nvidia :: cuda_version_upper_bound :: 13" \ + -p "nvidia :: cuda_version_lower_bound :: 13.0" \ + -p "nvidia :: cuda_version_upper_bound :: 14" \ -o . --pyproject-toml python-package/pyproject.toml diff --git a/ops/pipeline/build-variant-wheels.sh b/ops/pipeline/build-variant-wheels.sh index 87817063d43c..f6b4a349d22b 100755 --- a/ops/pipeline/build-variant-wheels.sh +++ b/ops/pipeline/build-variant-wheels.sh @@ -2,14 +2,14 @@ ## Build Python wheels using Wheel Variant prototype (WheelNext) ## This script runs inside a container (via GitHub Actions container support) ## -## Uses CUDA 12 build settings with RMM disabled. +## Uses CUDA 13 build settings with RMM disabled. ## Does not modify the package name (keeps default 'xgboost'). set -euo pipefail # Use the unified build script with explicit parameters: -# - CUDA 12 +# - CUDA 13 # - RMM disabled exec bash ops/pipeline/build-cuda.sh \ - --cuda-version 12 \ + --cuda-version 13 \ --use-rmm 0 diff --git a/ops/pipeline/get-image-tag.sh b/ops/pipeline/get-image-tag.sh index c69e7607dfd8..334cab33652f 100755 --- a/ops/pipeline/get-image-tag.sh +++ b/ops/pipeline/get-image-tag.sh @@ -7,4 +7,4 @@ # or PR number: # IMAGE_TAG=PR-88 -IMAGE_TAG=main +IMAGE_TAG=PR-97 diff --git a/ops/pipeline/nightly-test-cccl.sh b/ops/pipeline/nightly-test-cccl.sh index 4eadad262cca..4402b690d17f 100755 --- a/ops/pipeline/nightly-test-cccl.sh +++ b/ops/pipeline/nightly-test-cccl.sh @@ -14,7 +14,7 @@ source ops/pipeline/classify-git-branch.sh source ops/pipeline/get-docker-registry-details.sh source ops/pipeline/get-image-tag.sh -IMAGE_REPO="xgb-ci.gpu_build_cuda13_rockylinux8" +IMAGE_REPO="xgb-ci.gpu_build_rockylinux8" BUILD_IMAGE_URI="${DOCKER_REGISTRY_URL}/${IMAGE_REPO}:${IMAGE_TAG}" echo "--- Build XGBoost with CCCL ${cccl_version}" diff --git a/ops/pipeline/nightly-test-rmm.sh b/ops/pipeline/nightly-test-rmm.sh index 4f46f9bebba5..476632c0d2f2 100755 --- a/ops/pipeline/nightly-test-rmm.sh +++ b/ops/pipeline/nightly-test-rmm.sh @@ -14,7 +14,7 @@ source ops/pipeline/classify-git-branch.sh source ops/pipeline/get-docker-registry-details.sh source ops/pipeline/get-image-tag.sh -IMAGE_REPO="xgb-ci.gpu_build_cuda13_rockylinux8" +IMAGE_REPO="xgb-ci.gpu_build_rockylinux8" BUILD_IMAGE_URI="${DOCKER_REGISTRY_URL}/${IMAGE_REPO}:${IMAGE_TAG}" echo "--- Build XGBoost with RMM ${rmm_version}" diff --git a/ops/pipeline/test-python-wheel.sh b/ops/pipeline/test-python-wheel.sh index fd6163e1fb55..ce2bdfea7fcb 100755 --- a/ops/pipeline/test-python-wheel.sh +++ b/ops/pipeline/test-python-wheel.sh @@ -68,17 +68,10 @@ if [[ -n "${cuda_version}" ]]; then esac fi -# Set up conda environment based on CUDA version and suite +# Set up the suite's pre-built conda environment # Cannot set -u before Conda env activation case "$suite" in gpu|mgpu|gpu-arm64) - if [[ "${cuda_version}" == "13" ]]; then - # CUDA 13: Create conda environment on-the-fly - # Fix permissions for conda directories - gosu root chown -R "$(id -u):$(id -g)" /opt/miniforge/envs /opt/miniforge/pkgs/cache - gosu root chown "$(id -u):$(id -g)" /opt/miniforge/pkgs - mamba create -y -n gpu_test python=3.12 pytest cupy scipy numpy pandas scikit-learn joblib hypothesis - fi source activate gpu_test ;; cpu|cpu-arm64) diff --git a/ops/script/change_version.py b/ops/script/change_version.py index ab6e3a1d5674..197ca70d1dc1 100644 --- a/ops/script/change_version.py +++ b/ops/script/change_version.py @@ -62,7 +62,7 @@ def pypkg( with open(pyprj_path, "w") as fd: fd.write(pyprj) - make_pyproject(use_suffix="na", require_nccl_dep="cu12") + make_pyproject(use_suffix="na", require_nccl_dep="cu13") @cd(R_PACKAGE) diff --git a/ops/script/release_artifacts.py b/ops/script/release_artifacts.py index 44ba589da6bf..0e0b8d1a20d7 100644 --- a/ops/script/release_artifacts.py +++ b/ops/script/release_artifacts.py @@ -130,16 +130,16 @@ def make_python_sdist( dest = dist_dir / sdist_name shutil.move(src, dest) - # Build stub package `xgboost-cu12`. + # Build stub package `xgboost-cu13`. with DirectoryExcursion(ROOT): - make_pyproject(use_suffix="cu12", require_nccl_dep="na", create_stub=True) + make_pyproject(use_suffix="cu13", require_nccl_dep="na", create_stub=True) with DirectoryExcursion(ROOT / "python-package"): subprocess.run(["python", "-m", "build", "--sdist"], check=True) sdist_name = ( - f"xgboost_cu12-{release}{rc}{rc_ver}.tar.gz" + f"xgboost_cu13-{release}{rc}{rc_ver}.tar.gz" if rc - else f"xgboost_cu12-{release}.tar.gz" + else f"xgboost_cu13-{release}.tar.gz" ) src = DIST / sdist_name subprocess.run(["twine", "check", str(src)], check=True) @@ -156,7 +156,7 @@ def download_python_wheels(branch: str, commit_hash: str, outdir: Path) -> None: "macosx_10_15_x86_64", "macosx_12_0_arm64", ] - cu13_platforms = [ + cu12_platforms = [ "manylinux_2_28_x86_64", "manylinux_2_28_aarch64", ] @@ -173,7 +173,7 @@ def download_python_wheels(branch: str, commit_hash: str, outdir: Path) -> None: for pkg_name, platforms in [ ("xgboost", full_platforms), ("xgboost_cpu", minimal_platforms), - ("xgboost_cu13", cu13_platforms), + ("xgboost_cu12", cu12_platforms), ]: src_filename_prefix = f"{pkg_name}-{args.release}-py3-none-" target_filename_prefix = f"{pkg_name}-{args.release}-py3-none-" diff --git a/python-package/pyproject.toml b/python-package/pyproject.toml index 2f2455b693dc..0a729af1508e 100644 --- a/python-package/pyproject.toml +++ b/python-package/pyproject.toml @@ -1,4 +1,4 @@ -# Generated by `pypi_variants.py`, don't edit: '--use-suffix=na --require-nccl-dep=cu12' +# Generated by `pypi_variants.py`, don't edit: '--use-suffix=na --require-nccl-dep=cu13' [build-system] requires = ["scikit-build-core>=0.11.0"] build-backend = "scikit_build_core.build" @@ -28,7 +28,7 @@ classifiers = [ dependencies = [ "numpy", "scipy", - "nvidia-nccl-cu12 ; platform_system == 'Linux'", + "nvidia-nccl-cu13 ; platform_system == 'Linux'", ] [project.urls] From 1fc9bc54eb05ecdc917fe4bae3275261b056ead7 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 19:18:54 +0800 Subject: [PATCH 02/28] clang. --- .github/workflows/main.yml | 6 +- doc/contrib/coding_guide.rst | 5 +- ops/pipeline/build-cuda-clang.sh | 16 +- ops/pipeline/run-clang-tidy-clang-cuda.sh | 5 +- ops/pipeline/run-clang-tidy.sh | 14 - ops/script/run_clang_tidy.py | 309 ---------------------- 6 files changed, 19 insertions(+), 336 deletions(-) delete mode 100755 ops/pipeline/run-clang-tidy.sh delete mode 100755 ops/script/run_clang_tidy.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 16157fa09098..a1a039dfe602 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -149,7 +149,7 @@ jobs: build/testxgboost python-package/dist/*.whl build-cuda-clang: - name: Build CUDA with clang 21.1.8 (x86_64) + name: Build CUDA with clang 23.1.0.rc1 (x86_64) needs: ci-configure runs-on: - runs-on=${{ github.run_id }} @@ -168,8 +168,8 @@ jobs: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main with: - cache-key-prefix: ${{ github.job }}-clang21-cuda13 - - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 21.1.8 + cache-key-prefix: ${{ github.job }}-clang23rc1-cuda13 + - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 23.1.0.rc1 - run: sccache --show-stats audit-cuda-wheel: diff --git a/doc/contrib/coding_guide.rst b/doc/contrib/coding_guide.rst index e3464d9e322c..4c28fcb31e03 100644 --- a/doc/contrib/coding_guide.rst +++ b/doc/contrib/coding_guide.rst @@ -212,9 +212,8 @@ filter, checks, extra arguments, and ``warnings-as-errors`` filter. For example: The helper expects a clang toolchain with ``clang++``, ``clang-linker-wrapper``, and ``run-clang-tidy`` available either from the active conda base environment or from -``XGBOOST_CLANG_PREFIX``. When using conda, install both ``clangxx`` and -``clang-tools`` so the compiler resource directory and ``run-clang-tidy`` are both -present. +``XGBOOST_CLANG_PREFIX``. By default, it installs ``clang``, ``clangxx``, and +``clang-tools`` 23.1.0.rc1 from the ``conda-forge/label/llvm_rc`` channel. ********************************** Guide for handling user input data diff --git a/ops/pipeline/build-cuda-clang.sh b/ops/pipeline/build-cuda-clang.sh index f8cff9968f6a..55e5597050bd 100755 --- a/ops/pipeline/build-cuda-clang.sh +++ b/ops/pipeline/build-cuda-clang.sh @@ -4,7 +4,8 @@ set -euo pipefail -clang_version="21.1.8" +clang_version="23.1.0.rc1" +clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" cmake_version="4.2.3" build_dir="build-clang-cuda" target="xgboost" @@ -53,12 +54,17 @@ if [[ "${build_dir}" != /* ]]; then fi if [[ "${XGBOOST_SKIP_CLANG_INSTALL:-0}" != 1 ]]; then + clang_packages=( + "${clang_channel}::clang==${clang_version}" + "${clang_channel}::clangxx==${clang_version}" + "${clang_channel}::clang-tools==${clang_version}" + ) if command -v mamba >/dev/null 2>&1; then - mamba install -y -n base -c conda-forge "clangxx=${clang_version}" "clang-tools=${clang_version}" "cmake=${cmake_version}" + mamba install -y -n base -c conda-forge "${clang_packages[@]}" "cmake=${cmake_version}" elif command -v conda >/dev/null 2>&1; then - conda install -y -n base -c conda-forge "clangxx=${clang_version}" "clang-tools=${clang_version}" "cmake=${cmake_version}" + conda install -y -n base -c conda-forge "${clang_packages[@]}" "cmake=${cmake_version}" else - echo "clangxx=${clang_version}, clang-tools=${clang_version}, and cmake=${cmake_version} are required, but neither mamba nor conda is available." + echo "${clang_packages[*]} and cmake=${cmake_version} are required, but neither mamba nor conda is available." exit 1 fi fi @@ -94,7 +100,7 @@ echo "--- Build with clang-CUDA using ${clang_cxx}" "${cmake_bin}" --version if ! command -v clang-linker-wrapper >/dev/null 2>&1; then - echo "clang-linker-wrapper is required for clang CUDA offload linking. Install clang-tools=${clang_version}." + echo "clang-linker-wrapper is required for clang CUDA offload linking. Install ${clang_channel}::clang-tools==${clang_version}." exit 1 fi if [[ -f "${clang_bin_dir}/x86_64-conda-linux-gnu-clang++.cfg" ]] && diff --git a/ops/pipeline/run-clang-tidy-clang-cuda.sh b/ops/pipeline/run-clang-tidy-clang-cuda.sh index 0244763f817c..59225045afe0 100755 --- a/ops/pipeline/run-clang-tidy-clang-cuda.sh +++ b/ops/pipeline/run-clang-tidy-clang-cuda.sh @@ -3,7 +3,8 @@ set -euo pipefail -clang_version="21.1.8" +clang_version="23.1.0.rc1" +clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" cmake_version="4.2.3" build_dir="build-clang-tidy-cuda" jobs="${XGBOOST_TIDY_JOBS:-}" @@ -99,7 +100,7 @@ fi clang_run_tidy="${clang_prefix}/bin/run-clang-tidy" if [[ ! -x "${clang_run_tidy}" ]]; then if ! clang_run_tidy="$(command -v run-clang-tidy)"; then - echo "run-clang-tidy is required. Install clang-tools or set XGBOOST_CLANG_PREFIX to a clang prefix containing bin/run-clang-tidy." + echo "run-clang-tidy is required. Install ${clang_channel}::clang-tools==${clang_version} or set XGBOOST_CLANG_PREFIX to a clang prefix containing bin/run-clang-tidy." exit 1 fi fi diff --git a/ops/pipeline/run-clang-tidy.sh b/ops/pipeline/run-clang-tidy.sh deleted file mode 100755 index 5daade9f2fd8..000000000000 --- a/ops/pipeline/run-clang-tidy.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -source ops/pipeline/get-docker-registry-details.sh -source ops/pipeline/get-image-tag.sh - -IMAGE_URI=${DOCKER_REGISTRY_URL}/xgb-ci.clang_tidy:${IMAGE_TAG} - -echo "--- Run clang-tidy" -set -x -python3 ops/docker_run.py \ - --image-uri ${IMAGE_URI} \ - -- python3 ops/script/run_clang_tidy.py --cuda-archs 75 diff --git a/ops/script/run_clang_tidy.py b/ops/script/run_clang_tidy.py deleted file mode 100755 index 5f9096ab5f9c..000000000000 --- a/ops/script/run_clang_tidy.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env python -from __future__ import annotations - -import argparse -import json -import os -import re -import shutil -import subprocess -import sys -from multiprocessing import Pool, cpu_count -from time import time - - -def call(args: list[str]) -> tuple[int, int, str, list[str]]: - """Subprocess run wrapper.""" - completed = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - error_msg = completed.stdout.decode("utf-8") - # `workspace` is a name used in the CI container. Normally we should keep the dir - # as `xgboost`. - matched = re.search( - "(workspace|xgboost)/.*(ops|src|tests|include)/.*warning:", - error_msg, - re.MULTILINE, - ) - - if matched is None: - return_code = 0 - else: - return_code = 1 - return (completed.returncode, return_code, error_msg, args) - - -class ClangTidy: - """clang tidy wrapper. - Args: - args: Command line arguments. - cpp_lint: Run linter on C++ source code. - cuda_lint: Run linter on CUDA source code. - use_dmlc_gtest: Whether to use gtest bundled in dmlc-core. - """ - - def __init__(self, args: argparse.Namespace) -> None: - self.cpp_lint = args.cpp - self.cuda_lint = args.cuda - self.use_dmlc_gtest: bool = args.use_dmlc_gtest - self.cuda_archs = args.cuda_archs.copy() if args.cuda_archs else [] - - if args.tidy_version: - self.exe = "clang-tidy-" + str(args.tidy_version) - else: - self.exe = "clang-tidy" - - print("Run linter on CUDA: ", self.cuda_lint) - print("Run linter on C++:", self.cpp_lint) - print("Use dmlc gtest:", self.use_dmlc_gtest) - print("CUDA archs:", " ".join(self.cuda_archs)) - - if not self.cpp_lint and not self.cuda_lint: - raise ValueError("Both --cpp and --cuda are set to 0.") - self.root_path = os.path.abspath(os.path.curdir) - print("Project root:", self.root_path) - self.cdb_path = os.path.join(self.root_path, "cdb") - - def __enter__(self) -> "ClangTidy": - self.start = time() - if os.path.exists(self.cdb_path): - shutil.rmtree(self.cdb_path) - self._generate_cdb() - return self - - def __exit__(self, *args: list) -> None: - if os.path.exists(self.cdb_path): - shutil.rmtree(self.cdb_path) - self.end = time() - print("Finish running clang-tidy:", self.end - self.start) - - def _generate_cdb(self) -> None: - """Run CMake to generate compilation database.""" - os.mkdir(self.cdb_path) - os.chdir(self.cdb_path) - cmake_args = [ - "cmake", - self.root_path, - "-GNinja", # prevents cmake from using --option-files for include path. - "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", - "-DGOOGLE_TEST=ON", - "-DCMAKE_CXX_FLAGS='-Wno-clang-diagnostic-deprecated-declarations'", - ] - if self.use_dmlc_gtest: - cmake_args.append("-DUSE_DMLC_GTEST=ON") - else: - cmake_args.append("-DUSE_DMLC_GTEST=OFF") - - if self.cuda_lint: - cmake_args.extend(["-DUSE_CUDA=ON", "-DUSE_NCCL=ON"]) - if self.cuda_archs: - arch_list = ";".join(self.cuda_archs) - cmake_args.append(f"-DCMAKE_CUDA_ARCHITECTURES={arch_list}") - subprocess.run(cmake_args) - os.chdir(self.root_path) - - def convert_nvcc_command_to_clang(self, command: str) -> str: - """Convert nvcc flags to corresponding clang flags.""" - components = command.split() - compiler: str = components[0] - if compiler.find("nvcc") != -1: - compiler = "clang++" - components[0] = compiler - # check each component in a command - converted_components = [compiler] - - for i in range(1, len(components)): - if components[i] == "-lineinfo": - continue - elif components[i] == "-fuse-ld=gold": - continue - elif components[i] == "-fuse-ld=lld": - continue - elif components[i].find("--default-stream") != -1: - continue - elif components[i] == "-rdynamic": - continue - elif components[i] == "-Xfatbin=-compress-all": - continue - elif components[i] == "-forward-unknown-to-host-compiler": - continue - elif components[i] == "-x" and components[i + 1] == "cu": - # -x cu -> -x cuda - converted_components.append("-x") - converted_components.append("cuda") - components[i + 1] = "" - continue - elif components[i].find("-Xcompiler") != -1: - continue - elif components[i].find("--expt-") != -1: - continue - elif components[i].find("-ccbin") != -1: - continue - elif components[i].find("--generate-code") != -1: - keyword = "code=sm" - pos = components[i].find(keyword) - capability = components[i][ - pos + len(keyword) + 1 : pos + len(keyword) + 3 - ] - if pos != -1: - converted_components.append("--cuda-gpu-arch=sm_" + capability) - elif components[i].find("--std=c++14") != -1: - converted_components.append("-std=c++14") - elif components[i].startswith("-isystem="): - converted_components.extend(components[i].split("=")) - else: - converted_components.append(components[i]) - - converted_components.append("-isystem /usr/local/cuda/include/") - - command = "" - for c in converted_components: - command = command + " " + c - command = command.strip() - return command - - def _configure_flags(self, path: str, command: str) -> list[list[str]]: - src = os.path.join(self.root_path, "src").replace("/", "\\/") - include = os.path.join(self.root_path, "include").replace("/", "\\/") - - header_filter = "(" + src + "|" + include + ")" - common_args = [ - self.exe, - path, - "--header-filter=" + header_filter, - "--config-file=" + self.tidy_file, - ] - common_args.append("--") - command = self.convert_nvcc_command_to_clang(command) - - command_split = command.split()[1:] # remove clang/c++/g++ - if "-c" in command_split: - index = command_split.index("-c") - del command_split[index + 1] - command_split.remove("-c") - if "-o" in command_split: - index = command_split.index("-o") - del command_split[index + 1] - command_split.remove("-o") - - common_args.extend(command_split) - - # Two passes, one for device code another for host code. - if path.endswith("cu"): - args = [common_args.copy(), common_args.copy()] - args[0].append("--cuda-host-only") - args[1].append("--cuda-device-only") - else: - args = [common_args.copy()] - for a in args: - a.append("-Wno-unused-command-line-argument") - return args - - def _configure(self) -> list[list[str]]: - """Load and configure compile_commands and clang_tidy.""" - - def should_lint(path: str) -> bool: - if not self.cpp_lint and path.endswith(".cc"): - return False - isxgb = path.find("dmlc-core") == -1 - isxgb = isxgb and (not path.startswith(self.cdb_path)) - if isxgb: - print(path) - return True - return False - - cdb_file = os.path.join(self.cdb_path, "compile_commands.json") - with open(cdb_file, "r") as fd: - self.compile_commands = json.load(fd) - - self.tidy_file = os.path.join(self.root_path, ".clang-tidy") - all_files = [] - for entry in self.compile_commands: - path = entry["file"] - if should_lint(path): - args = self._configure_flags(path, entry["command"]) - all_files.extend(args) - return all_files - - def run(self) -> bool: - """Run clang-tidy.""" - all_files = self._configure() - passed = True - BAR = "-" * 32 - with Pool(cpu_count()) as pool: - results = pool.map(call, all_files) - for i, (process_status, tidy_status, msg, args) in enumerate(results): - # Don't enforce clang-tidy to pass for now due to namespace - # for cub in thrust is not correct. - if tidy_status == 1: - passed = False - print( - BAR, - "\n" "Command args:", - " ".join(args), - ", ", - "Process return code:", - process_status, - ", ", - "Tidy result code:", - tidy_status, - ", ", - "Message:\n", - msg, - BAR, - "\n", - ) - if not passed: - print( - "Errors in `thrust` namespace can be safely ignored.", - "Please address rest of the clang-tidy warnings.", - ) - return passed - - -def test_tidy(args: argparse.Namespace) -> None: - """See if clang-tidy and our regex is working correctly. There are many subtleties - we need to be careful. Tests here are not thorough, at least we want to guarantee - tidy is not missing anything on the CI. - - """ - root_path = os.path.abspath(os.path.curdir) - tidy_file = os.path.join(root_path, ".clang-tidy") - test_file_path = os.path.join(root_path, "ops", "script", "test_tidy.cc") - - tidy_config = "--config-file=" + tidy_file - if not args.tidy_version: - tidy = "clang-tidy" - else: - tidy = "clang-tidy-" + str(args.tidy_version) - cmd = [tidy, tidy_config, test_file_path] - proc_code, tidy_status, error_msg, _ = call(cmd) - if proc_code != 0 or tidy_status != 1: - raise RuntimeError(error_msg) - print("clang-tidy is working.") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Run clang-tidy.") - parser.add_argument("--cpp", type=int, default=1) - parser.add_argument( - "--tidy-version", - type=int, - default=None, - help="Specify the version of preferred clang-tidy.", - ) - parser.add_argument("--cuda", type=int, default=1) - parser.add_argument( - "--use-dmlc-gtest", - action="store_true", - help="Whether to use gtest bundled in dmlc-core.", - ) - parser.add_argument( - "--cuda-archs", action="append", help="List of CUDA archs to build" - ) - args = parser.parse_args() - - test_tidy(args) - - with ClangTidy(args) as linter: - passed = linter.run() - if not passed: - sys.exit(1) From 63943d38b1c39646dcc27fde89e33200794ff2f0 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 19:28:28 +0800 Subject: [PATCH 03/28] rc2 --- .github/workflows/main.yml | 6 +++--- doc/contrib/coding_guide.rst | 2 +- ops/pipeline/build-cuda-clang.sh | 2 +- ops/pipeline/run-clang-tidy-clang-cuda.sh | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a1a039dfe602..012244a20762 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -149,7 +149,7 @@ jobs: build/testxgboost python-package/dist/*.whl build-cuda-clang: - name: Build CUDA with clang 23.1.0.rc1 (x86_64) + name: Build CUDA with clang 23.1.0.rc2 (x86_64) needs: ci-configure runs-on: - runs-on=${{ github.run_id }} @@ -168,8 +168,8 @@ jobs: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main with: - cache-key-prefix: ${{ github.job }}-clang23rc1-cuda13 - - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 23.1.0.rc1 + cache-key-prefix: ${{ github.job }}-clang23rc2-cuda13 + - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 23.1.0.rc2 - run: sccache --show-stats audit-cuda-wheel: diff --git a/doc/contrib/coding_guide.rst b/doc/contrib/coding_guide.rst index 4c28fcb31e03..78b71ae4d36c 100644 --- a/doc/contrib/coding_guide.rst +++ b/doc/contrib/coding_guide.rst @@ -213,7 +213,7 @@ filter, checks, extra arguments, and ``warnings-as-errors`` filter. For example: The helper expects a clang toolchain with ``clang++``, ``clang-linker-wrapper``, and ``run-clang-tidy`` available either from the active conda base environment or from ``XGBOOST_CLANG_PREFIX``. By default, it installs ``clang``, ``clangxx``, and -``clang-tools`` 23.1.0.rc1 from the ``conda-forge/label/llvm_rc`` channel. +``clang-tools`` 23.1.0.rc2 from the ``conda-forge/label/llvm_rc`` channel. ********************************** Guide for handling user input data diff --git a/ops/pipeline/build-cuda-clang.sh b/ops/pipeline/build-cuda-clang.sh index 55e5597050bd..6d77b970018b 100755 --- a/ops/pipeline/build-cuda-clang.sh +++ b/ops/pipeline/build-cuda-clang.sh @@ -4,7 +4,7 @@ set -euo pipefail -clang_version="23.1.0.rc1" +clang_version="23.1.0.rc2" clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" cmake_version="4.2.3" build_dir="build-clang-cuda" diff --git a/ops/pipeline/run-clang-tidy-clang-cuda.sh b/ops/pipeline/run-clang-tidy-clang-cuda.sh index 59225045afe0..1a0c89c62bcf 100755 --- a/ops/pipeline/run-clang-tidy-clang-cuda.sh +++ b/ops/pipeline/run-clang-tidy-clang-cuda.sh @@ -3,7 +3,7 @@ set -euo pipefail -clang_version="23.1.0.rc1" +clang_version="23.1.0.rc2" clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" cmake_version="4.2.3" build_dir="build-clang-tidy-cuda" From eb2255128511cfa9f2c8578996f9e8b4e1baa165 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 19:35:53 +0800 Subject: [PATCH 04/28] downgrade. --- .github/workflows/lint.yml | 4 ++-- .github/workflows/main.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2a1f37b74b15..ce3927fa9497 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,14 +26,14 @@ jobs: tag-prefix: lint clang-tidy: - name: Run clang-tidy + name: Run clang-tidy with CUDA 12.9 needs: ci-configure runs-on: - runs-on=${{ github.run_id }} - runner=linux-amd64-cpu - tag=lint-clang-tidy-clang-cuda container: - image: ${{ needs.ci-configure.outputs.docker_registry }}/xgb-ci.gpu_build_rockylinux8:${{ needs.ci-configure.outputs.image_tag }} + image: ${{ needs.ci-configure.outputs.docker_registry }}/xgb-ci.gpu_build_cuda12_rockylinux8:${{ needs.ci-configure.outputs.image_tag }} credentials: username: ${{ needs.ci-configure.outputs.docker_username }} password: ${{ needs.ci-configure.outputs.docker_password }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 012244a20762..8e7e320ba661 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -149,7 +149,7 @@ jobs: build/testxgboost python-package/dist/*.whl build-cuda-clang: - name: Build CUDA with clang 23.1.0.rc2 (x86_64) + name: Build CUDA 12.9 with clang 23.1.0.rc2 (x86_64) needs: ci-configure runs-on: - runs-on=${{ github.run_id }} @@ -157,7 +157,7 @@ jobs: - tag=main-build-cuda-clang - extras=s3-cache container: - image: ${{ needs.ci-configure.outputs.docker_registry }}/xgb-ci.gpu_build_rockylinux8:${{ needs.ci-configure.outputs.image_tag }} + image: ${{ needs.ci-configure.outputs.docker_registry }}/xgb-ci.gpu_build_cuda12_rockylinux8:${{ needs.ci-configure.outputs.image_tag }} credentials: username: ${{ needs.ci-configure.outputs.docker_username }} password: ${{ needs.ci-configure.outputs.docker_password }} @@ -168,7 +168,7 @@ jobs: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main with: - cache-key-prefix: ${{ github.job }}-clang23rc2-cuda13 + cache-key-prefix: ${{ github.job }}-clang23rc2-cuda12 - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 23.1.0.rc2 - run: sccache --show-stats From 5857f64ce2deb58d3cd74481d96029c9787a5ba4 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 22:19:32 +0800 Subject: [PATCH 05/28] clang tidy. --- include/xgboost/json.h | 5 +++-- src/common/json.cc | 2 +- src/common/json_utils.h | 4 ++-- src/data/array_interface.cc | 2 +- src/data/array_interface.h | 12 +++++++----- src/data/data.cc | 2 +- src/tree/gpu_hist/histogram.cu | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/xgboost/json.h b/include/xgboost/json.h index 4abab6cf4f2a..bda358deae21 100644 --- a/include/xgboost/json.h +++ b/include/xgboost/json.h @@ -12,6 +12,7 @@ #include #include #include +#include #include // std::enable_if_t #include #include @@ -69,7 +70,7 @@ class Value { virtual bool operator==(Value const& rhs) const = 0; virtual Value& operator=(Value const& rhs) = delete; - std::string TypeStr() const; + std::string_view TypeStr() const; private: ValueKind kind_; @@ -85,7 +86,7 @@ T* Cast(U* value) { if (IsA(value)) { return dynamic_cast(value); } else { - LOG(FATAL) << "Invalid cast, from " + value->TypeStr() + " to " + T().TypeStr(); + LOG(FATAL) << "Invalid cast, from " << value->TypeStr() << " to " << T().TypeStr(); } return dynamic_cast(value); // suppress compiler warning. } diff --git a/src/common/json.cc b/src/common/json.cc index 67e718f34e5c..1cc13a78fce4 100644 --- a/src/common/json.cc +++ b/src/common/json.cc @@ -147,7 +147,7 @@ void JsonWriter::Visit(JsonBoolean const* boolean) { } // Value -std::string Value::TypeStr() const { +std::string_view Value::TypeStr() const { switch (kind_) { case ValueKind::kString: return "String"; diff --git a/src/common/json_utils.h b/src/common/json_utils.h index a9e07c31e082..ff5f88bb28ca 100644 --- a/src/common/json_utils.h +++ b/src/common/json_utils.h @@ -27,12 +27,12 @@ std::enable_if_t TypeCheckImpl(Json const &value) { template std::string TypeCheckError() { - return "`" + Head{}.TypeStr() + "`"; + return "`" + std::string{Head{}.TypeStr()} + "`"; } template std::enable_if_t TypeCheckError() { - return "`" + Head{}.TypeStr() + "`, " + TypeCheckError(); + return "`" + std::string{Head{}.TypeStr()} + "`, " + TypeCheckError(); } } // namespace detail diff --git a/src/data/array_interface.cc b/src/data/array_interface.cc index 08d90199f457..25fc602a34f6 100644 --- a/src/data/array_interface.cc +++ b/src/data/array_interface.cc @@ -14,7 +14,7 @@ namespace xgboost { std::string ArrayInterfaceHandler::TypeStr(Type type) { auto name_fn = [](std::int32_t bits, char t) { - return std::to_string(bits) + "-bit " + ArrayInterfaceErrors::TypeStr(t); + return std::to_string(bits) + "-bit " + std::string{ArrayInterfaceErrors::TypeStr(t)}; }; switch (type) { case kF2: diff --git a/src/data/array_interface.h b/src/data/array_interface.h index ce393c0fffa4..37777e5fa5c6 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -92,7 +92,7 @@ struct ArrayInterfaceErrors { } static std::string UnSupportedType(StringView typestr) { - return TypeStr(typestr[1]) + "-" + typestr[2] + " is not supported."; + return std::string{TypeStr(typestr[1])} + "-" + typestr[2] + " is not supported."; } }; @@ -334,11 +334,13 @@ template <> struct ToDType { static constexpr ArrayInterfaceHandler::Type kType = ArrayInterfaceHandler::kF8; }; +// NumPy's 128-bit floating-point array interface maps to long double on supported hosts. +// NOLINTBEGIN(google-runtime-float) template -struct ToDType && sizeof(long double) == 16>> { +struct ToDType && sizeof(long double) == 16>> { static constexpr ArrayInterfaceHandler::Type kType = ArrayInterfaceHandler::kF16; }; +// NOLINTEND(google-runtime-float) // uint template <> struct ToDType { @@ -535,7 +537,7 @@ class ArrayInterface { } #else case T::kF16: - return func(reinterpret_cast(data)); + return func(reinterpret_cast(data)); // NOLINT(google-runtime-float) #endif case T::kI1: return func(reinterpret_cast(data)); @@ -621,7 +623,7 @@ auto DispatchDType(ArrayInterfaceHandler::Type dtype, Fn dispatch) { return dispatch(double{}); } case ArrayInterfaceHandler::kF16: { - using T = long double; + using T = long double; // NOLINT(google-runtime-float) CHECK(sizeof(T) == 16) << error::NoF128(); // Avoid invalid type. if constexpr (sizeof(T) == 16) { diff --git a/src/data/data.cc b/src/data/data.cc index 7868074ccbac..046acd2eb76d 100644 --- a/src/data/data.cc +++ b/src/data/data.cc @@ -1108,7 +1108,7 @@ bst_idx_t SparsePage::Push(AdapterBatchT const& batch, float missing, std::int32 auto& data_vec = data.HostVector(); size_t builder_base_row_offset = this->Size(); - common::ParallelGroupBuilder::type::value_type, + common::ParallelGroupBuilder::value_type, kIsRowMajor> builder(&offset_vec, &data_vec, builder_base_row_offset); // Estimate expected number of rows by using last element in batch diff --git a/src/tree/gpu_hist/histogram.cu b/src/tree/gpu_hist/histogram.cu index 654121ab3fe9..6c5cb8f7861e 100644 --- a/src/tree/gpu_hist/histogram.cu +++ b/src/tree/gpu_hist/histogram.cu @@ -599,7 +599,7 @@ void DeviceHistogramBuilder::AllReduceHist(Context const* ctx, bst_node_t nidx, std::size_t num_histograms) { this->monitor_.Start(__func__); auto d_node_hist = hist_.GetNodeHistogram(nidx); - using ReduceT = typename std::remove_pointer::type::ValueT; + using ReduceT = typename std::remove_pointer_t::ValueT; auto rc = collective::GlobalSum( ctx, linalg::MakeVec(reinterpret_cast(d_node_hist.data()), d_node_hist.size() * 2 * num_histograms, ctx->Device())); From 3326e4bcbb104ff1b3ca7749907c631641de0dfc Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 22:29:03 +0800 Subject: [PATCH 06/28] lint. --- src/data/array_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/array_interface.h b/src/data/array_interface.h index 37777e5fa5c6..20f3cb48142c 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -253,8 +253,8 @@ class ArrayInterfaceHandler { * \brief Extracts the optiona `strides' field and returns whether the array is c-contiguous. */ template - static bool ExtractStride(Object::Map const &array, size_t itemsize, - size_t (&shape)[D], size_t (&stride)[D]) { + static bool ExtractStride(Object::Map const &array, size_t itemsize, size_t (&shape)[D], + size_t (&stride)[D]) { auto strides_it = array.find("strides"); // No stride is provided if (strides_it == array.cend() || IsA(strides_it->second)) { From f2384cbae166f4e8cd478d1fc39c7954ebfad655 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 22:32:07 +0800 Subject: [PATCH 07/28] clang. --- src/data/array_interface.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/data/array_interface.h b/src/data/array_interface.h index 20f3cb48142c..36ca8907cddd 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2024, XGBoost Contributors + * Copyright 2019-2026, XGBoost Contributors * \file array_interface.h * \brief View of __array_interface__ */ @@ -12,6 +12,7 @@ #include // for numeric_limits #include // for map #include // for string +#include // for string_view #include // for alignment_of_v, remove_pointer_t, invoke_result_t #include // for vector @@ -55,7 +56,7 @@ struct ArrayInterfaceErrors { return str.c_str(); } - static std::string TypeStr(char c) { + static std::string_view TypeStr(char c) { switch (c) { case 't': return "Bit field"; @@ -91,7 +92,7 @@ struct ArrayInterfaceErrors { } } - static std::string UnSupportedType(StringView typestr) { + static std::string UnSupportedType(std::string_view typestr) { return std::string{TypeStr(typestr[1])} + "-" + typestr[2] + " is not supported."; } }; @@ -409,7 +410,7 @@ class ArrayInterface { ArrayInterfaceHandler::Validate(array); auto typestr = get(array.at("typestr")); - this->AssignType(StringView{typestr}); + this->AssignType(std::string_view{typestr}); ArrayInterfaceHandler::ExtractShape(array, shape); std::size_t itemsize = typestr[2] - '0'; is_contiguous = ArrayInterfaceHandler::ExtractStride(array, itemsize, shape, strides); @@ -468,7 +469,7 @@ class ArrayInterface { explicit ArrayInterface(StringView str) : ArrayInterface{Json::Load(str)} {} - void AssignType(StringView typestr) { + void AssignType(std::string_view typestr) { using T = ArrayInterfaceHandler::Type; if (typestr.size() == 4 && typestr[1] == 'f' && typestr[2] == '1' && typestr[3] == '6') { CHECK(sizeof(long double) == 16) << error::NoF128(); From f77bca0420a6455c18a3a2a579ad45015267a419 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 22:34:43 +0800 Subject: [PATCH 08/28] lint. --- src/data/array_interface.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/array_interface.h b/src/data/array_interface.h index 36ca8907cddd..1b57ed99540d 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -93,7 +93,7 @@ struct ArrayInterfaceErrors { } static std::string UnSupportedType(std::string_view typestr) { - return std::string{TypeStr(typestr[1])} + "-" + typestr[2] + " is not supported."; + return std::string{TypeStr(typestr[1])} + "-" + typestr[2] + " is not supported."; // NOLINT } }; @@ -538,7 +538,7 @@ class ArrayInterface { } #else case T::kF16: - return func(reinterpret_cast(data)); // NOLINT(google-runtime-float) + return func(reinterpret_cast(data)); // NOLINT #endif case T::kI1: return func(reinterpret_cast(data)); @@ -624,7 +624,7 @@ auto DispatchDType(ArrayInterfaceHandler::Type dtype, Fn dispatch) { return dispatch(double{}); } case ArrayInterfaceHandler::kF16: { - using T = long double; // NOLINT(google-runtime-float) + using T = long double; // NOLINT CHECK(sizeof(T) == 16) << error::NoF128(); // Avoid invalid type. if constexpr (sizeof(T) == 16) { From 16659d9f709bf78ee61469b8cf033b25d2be5ec3 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 23:43:47 +0800 Subject: [PATCH 09/28] Drop all death tests. --- tests/cpp/common/test_span.cu | 153 ---------------------------------- 1 file changed, 153 deletions(-) diff --git a/tests/cpp/common/test_span.cu b/tests/cpp/common/test_span.cu index 9c2bdc65cd34..c3d9e2c50870 100644 --- a/tests/cpp/common/test_span.cu +++ b/tests/cpp/common/test_span.cu @@ -209,37 +209,6 @@ TEST(GPUSpan, Compare) { ASSERT_EQ(status.Get(), 1); } -struct TestElementAccess { - private: - Span span_; - - public: - XGBOOST_DEVICE explicit TestElementAccess (Span _span) : span_(_span) {} - - XGBOOST_DEVICE float operator()(size_t _idx) { - float tmp = span_[_idx]; - return tmp; - } -}; - -TEST(GPUSpanDeathTest, ElementAccess) { - dh::safe_cuda(cudaSetDevice(0)); - auto test_element_access = []() { - thrust::host_vector h_vec (16); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - dh::LaunchN(17, TestElementAccess{span}); - }; - - testing::internal::CaptureStdout(); - EXPECT_DEATH(test_element_access(), ""); - std::string output = testing::internal::GetCapturedStdout(); -} - __global__ void TestFirstDynamicKernel(Span _span) { _span.first::index_type>(-1)>(); } @@ -253,134 +222,12 @@ __global__ void TestLastStaticKernel(Span _span) { _span.last(static_cast::index_type>(-1)); } -TEST(GPUSpanDeathTest, FirstLast) { - // We construct vectors multiple times since thrust can not recover from - // death test. - auto lambda_first_dy = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestFirstDynamicKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_first_dy(), ""); - std::string output = testing::internal::GetCapturedStdout(); - - auto lambda_first_static = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestFirstStaticKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_first_static(), ""); - output = testing::internal::GetCapturedStdout(); - - auto lambda_last_dy = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestLastDynamicKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_last_dy(), ""); - output = testing::internal::GetCapturedStdout(); - - auto lambda_last_static = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestLastStaticKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_last_static(), ""); - output = testing::internal::GetCapturedStdout(); -} - -namespace { -void TestFrontBack() { - Span s; - EXPECT_DEATH( - { - // make sure the termination happens inside this test. - try { - dh::LaunchN(1, [=] __device__(size_t) { s.front(); }); - dh::safe_cuda(cudaDeviceSynchronize()); - dh::safe_cuda(cudaGetLastError()); - } catch (dmlc::Error const& e) { - std::terminate(); - } - }, - ""); - EXPECT_DEATH( - { - try { - dh::LaunchN(1, [=] __device__(size_t) { s.back(); }); - dh::safe_cuda(cudaDeviceSynchronize()); - dh::safe_cuda(cudaGetLastError()); - } catch (dmlc::Error const& e) { - std::terminate(); - } - }, - ""); -} -} // namespace - -TEST(GPUSpanDeathTest, FrontBack) { - TestFrontBack(); -} - __global__ void TestSubspanDynamicKernel(Span _span) { _span.subspan(16, 0); } __global__ void TestSubspanStaticKernel(Span _span) { _span.subspan<16>(); } -TEST(GPUSpanDeathTest, Subspan) { - auto lambda_subspan_dynamic = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestSubspanDynamicKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_subspan_dynamic(), ""); - std::string output = testing::internal::GetCapturedStdout(); - - auto lambda_subspan_static = []() { - thrust::host_vector h_vec (4); - InitializeRange(h_vec.begin(), h_vec.end()); - - thrust::device_vector d_vec (h_vec.size()); - thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - - Span span (d_vec.data().get(), d_vec.size()); - TestSubspanStaticKernel<<<1, 1>>>(span); - }; - testing::internal::CaptureStdout(); - EXPECT_DEATH(lambda_subspan_static(), ""); - output = testing::internal::GetCapturedStdout(); -} TEST(GPUSpanIter, Construct) { dh::safe_cuda(cudaSetDevice(0)); From 66e789c88f9cf84a98515ad14faada1902aac9a8 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Thu, 30 Jul 2026 23:45:46 +0800 Subject: [PATCH 10/28] lint. --- tests/cpp/common/test_span.cu | 60 ++++++++++++++--------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/tests/cpp/common/test_span.cu b/tests/cpp/common/test_span.cu index c3d9e2c50870..6761645f7bfb 100644 --- a/tests/cpp/common/test_span.cu +++ b/tests/cpp/common/test_span.cu @@ -17,29 +17,23 @@ namespace common { struct TestStatus { private: - int *status_; + int* status_; public: - TestStatus () { + TestStatus() { dh::safe_cuda(cudaMalloc(&status_, sizeof(int))); int h_status = 1; - dh::safe_cuda(cudaMemcpy(status_, &h_status, - sizeof(int), cudaMemcpyHostToDevice)); - } - ~TestStatus() { - dh::safe_cuda(cudaFree(status_)); + dh::safe_cuda(cudaMemcpy(status_, &h_status, sizeof(int), cudaMemcpyHostToDevice)); } + ~TestStatus() { dh::safe_cuda(cudaFree(status_)); } int Get() { int h_status; - dh::safe_cuda(cudaMemcpy(&h_status, status_, - sizeof(int), cudaMemcpyDeviceToHost)); + dh::safe_cuda(cudaMemcpy(&h_status, status_, sizeof(int), cudaMemcpyDeviceToHost)); return h_status; } - int* Data() { - return status_; - } + int* Data() { return status_; } }; __global__ void TestFromOtherKernel(Span span) { @@ -64,18 +58,18 @@ __global__ void TestFromOtherKernelConst(Span span) { * \brief Here we just test whether the code compiles. */ TEST(GPUSpan, FromOther) { - thrust::host_vector h_vec (16); + thrust::host_vector h_vec(16); std::iota(h_vec.begin(), h_vec.end(), 0); - thrust::device_vector d_vec (h_vec.size()); + thrust::device_vector d_vec(h_vec.size()); thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); // dynamic extent { - Span span (d_vec.data().get(), d_vec.size()); + Span span(d_vec.data().get(), d_vec.size()); TestFromOtherKernel<<<1, 16>>>(span); } { - Span span (d_vec.data().get(), d_vec.size()); + Span span(d_vec.data().get(), d_vec.size()); TestFromOtherKernelConst<<<1, 16>>>(span); } // static extent @@ -107,11 +101,10 @@ template struct TestEqual { private: T *lhs_, *rhs_; - int *status_; + int* status_; public: - TestEqual(T* _lhs, T* _rhs, int * _status) : - lhs_(_lhs), rhs_(_rhs), status_(_status) {} + TestEqual(T* _lhs, T* _rhs, int* _status) : lhs_(_lhs), rhs_(_rhs), status_(_status) {} XGBOOST_DEVICE void operator()(size_t _idx) { bool res = lhs_[_idx] == rhs_[_idx]; @@ -123,16 +116,16 @@ TEST(GPUSpan, WithTrust) { dh::safe_cuda(cudaSetDevice(0)); // Not adviced to initialize span with host_vector, since h_vec.data() is // a host function. - thrust::host_vector h_vec (16); + thrust::host_vector h_vec(16); std::iota(h_vec.begin(), h_vec.end(), 0); - thrust::device_vector d_vec (h_vec.size()); + thrust::device_vector d_vec(h_vec.size()); thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); // Can't initialize span with device_vector, since d_vec.data() is not raw // pointer { - Span s (d_vec.data().get(), d_vec.size()); + Span s(d_vec.data().get(), d_vec.size()); ASSERT_EQ(d_vec.size(), s.size()); ASSERT_EQ(d_vec.data().get(), s.data()); @@ -140,13 +133,12 @@ TEST(GPUSpan, WithTrust) { { TestStatus status; - thrust::device_vector d_vec1 (d_vec.size()); + thrust::device_vector d_vec1(d_vec.size()); thrust::copy(thrust::device, d_vec.begin(), d_vec.end(), d_vec1.begin()); - Span s (d_vec1.data().get(), d_vec.size()); + Span s(d_vec1.data().get(), d_vec.size()); - dh::LaunchN(16, TestEqual{ - thrust::raw_pointer_cast(d_vec1.data()), - s.data(), status.Data()}); + dh::LaunchN(16, + TestEqual{thrust::raw_pointer_cast(d_vec1.data()), s.data(), status.Data()}); ASSERT_EQ(status.Get(), 1); // FIXME(trivialfis): memory error! @@ -180,13 +172,13 @@ __global__ void TestModifyKernel(Span span) { } TEST(GPUSpan, Modify) { - thrust::host_vector h_vec (16); + thrust::host_vector h_vec(16); InitializeRange(h_vec.begin(), h_vec.end()); - thrust::device_vector d_vec (h_vec.size()); + thrust::device_vector d_vec(h_vec.size()); thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin()); - Span span (d_vec.data().get(), d_vec.size()); + Span span(d_vec.data().get(), d_vec.size()); TestModifyKernel<<<1, 16>>>(span); @@ -222,12 +214,8 @@ __global__ void TestLastStaticKernel(Span _span) { _span.last(static_cast::index_type>(-1)); } -__global__ void TestSubspanDynamicKernel(Span _span) { - _span.subspan(16, 0); -} -__global__ void TestSubspanStaticKernel(Span _span) { - _span.subspan<16>(); -} +__global__ void TestSubspanDynamicKernel(Span _span) { _span.subspan(16, 0); } +__global__ void TestSubspanStaticKernel(Span _span) { _span.subspan<16>(); } TEST(GPUSpanIter, Construct) { dh::safe_cuda(cudaSetDevice(0)); From 9fa34ad811fe3c8ddd400933a32dd1398f3aa9bc Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 02:48:32 +0800 Subject: [PATCH 11/28] Remove federated tests. --- .github/workflows/main.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8e7e320ba661..6461f5232655 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -76,14 +76,6 @@ jobs: run: | source activate linux_cpu_test bash ops/pipeline/build-cpu.sh ${{ matrix.build_suite }} - - name: Test federated learning on CPU - if: matrix.variant == 'default' - shell: bash -l {0} - run: | - source activate linux_cpu_test - conda install scikit-build-core -y - cd python-package && pip install -e . --no-deps --no-build-isolation && cd - - timeout 600s pytest -v -s -rxXs --durations=0 tests/test_distributed/test_federated - run: sccache --show-stats - name: Build and test with sanitizer if: matrix.variant == 'sanitizer' From b09eea6bf5bd339d064abc18f14f6161e1ac94b4 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 09:41:56 +0800 Subject: [PATCH 12/28] split up the env. --- .github/workflows/main.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6461f5232655..103500af1f00 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -332,13 +332,13 @@ jobs: fail-fast: false matrix: include: - # CUDA 12 artifact compatibility tests (using the default CUDA 13 runtime) + # CUDA 12 artifact tests using the native CUDA 12.9 runtime # Note: --gpus all provides GPU access; --privileged is not needed for basic GPU tests - cuda_version: 12 suite: gpu arch: x86_64 runner: linux-amd64-gpu - image_repo: xgb-ci.gpu + image_repo: xgb-ci.gpu_cuda12 artifact_from: build-cuda12-x86_64 container_options: "--gpus all --privileged" test_args: "" @@ -346,7 +346,7 @@ jobs: suite: gpu arch: aarch64 runner: linux-arm64-gpu - image_repo: xgb-ci.gpu_aarch64 + image_repo: xgb-ci.gpu_cuda12_aarch64 artifact_from: build-cuda12-aarch64 container_options: "--gpus all --privileged" test_args: "" @@ -354,7 +354,7 @@ jobs: suite: mgpu arch: x86_64 runner: linux-amd64-mgpu - image_repo: xgb-ci.gpu + image_repo: xgb-ci.gpu_cuda12 artifact_from: build-cuda12-x86_64 # mgpu needs --shm-size for NCCL shared memory communication container_options: "--gpus all --shm-size=4g --privileged" @@ -417,26 +417,26 @@ jobs: fail-fast: false matrix: include: - # xgboost-cu12 tests (using the default CUDA 13 runtime) + # xgboost-cu12 tests using the native CUDA 12.9 runtime - cuda_version: 12 description: GPU-x86_64-CUDA-12 - image_repo: xgb-ci.gpu + image_repo: xgb-ci.gpu_cuda12 suite: gpu runner: linux-amd64-gpu artifact_from: audit-cuda12-wheel-x86_64 container_options: "--gpus all --privileged" - cuda_version: 12 description: Multi-GPU-x86_64-CUDA-12 - image_repo: xgb-ci.gpu + image_repo: xgb-ci.gpu_cuda12 suite: mgpu runner: linux-amd64-mgpu artifact_from: audit-cuda12-wheel-x86_64 # mgpu needs --shm-size for NCCL shared memory communication container_options: "--gpus all --shm-size=4g --privileged" - # xgboost-cu12 aarch64 test (using the default CUDA 13 runtime) + # xgboost-cu12 aarch64 test using the native CUDA 12.9 runtime - cuda_version: 12 description: GPU-arm64-CUDA-12 - image_repo: xgb-ci.gpu_aarch64 + image_repo: xgb-ci.gpu_cuda12_aarch64 suite: gpu-arm64 runner: linux-arm64-gpu artifact_from: audit-cuda12-wheel-aarch64 From 629c79a4a24ba936e5f9b106fb1209d69634041f Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 10:01:11 +0800 Subject: [PATCH 13/28] Update document. --- doc/contrib/ci.rst | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/contrib/ci.rst b/doc/contrib/ci.rst index 76d055fb68ef..6c18ad07ab9a 100644 --- a/doc/contrib/ci.rst +++ b/doc/contrib/ci.rst @@ -153,7 +153,7 @@ Invoke ``ops/docker_run.py`` from the main ``dmlc/xgboost`` repo as follows: python3 ops/docker_run.py \ --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/[image_repo]:[image_tag] \ [--use-gpus] \ - -- "command to run inside the container" + -- command [arguments...] where ``--use-gpus`` should be specified to expose NVIDIA GPUs to the Docker container. @@ -164,13 +164,13 @@ For example: # Run without GPU python3 ops/docker_run.py \ --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.cpu:main \ - -- bash ops/pipeline/build-cpu-impl.sh cpu + -- bash ops/pipeline/test-python-wheel.sh --suite cpu # Run with NVIDIA GPU python3 ops/docker_run.py \ --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ --use-gpus \ - -- bash ops/pipeline/test-python-wheel.sh gpu + -- bash ops/pipeline/test-python-wheel.sh --suite gpu --cuda-version 13 Optionally, you can specify ``--run-args`` to pass extra arguments to ``docker run``: @@ -182,7 +182,7 @@ Optionally, you can specify ``--run-args`` to pass extra arguments to ``docker r --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ --use-gpus \ --run-args='--shm-size=4g --privileged' \ - -- bash ops/pipeline/test-python-wheel.sh gpu + -- bash ops/pipeline/test-python-wheel.sh --suite mgpu --cuda-version 13 See :ref:`ci_container_infra` to read about how containers are built and managed in the CI pipelines. @@ -215,7 +215,7 @@ Examples: useful tasks for local development export DOCKER_REGISTRY=492475357299.dkr.ecr.us-west-2.amazonaws.com python3 ops/docker_run.py \ --image-uri ${DOCKER_REGISTRY}/xgb-ci.cpu:main \ - -- ops/pipeline/test-python-wheel.sh cpu + -- ops/pipeline/test-python-wheel.sh --suite cpu * Run Python tests with GPU algorithm @@ -225,7 +225,7 @@ Examples: useful tasks for local development python3 ops/docker_run.py \ --image-uri ${DOCKER_REGISTRY}/xgb-ci.gpu:main \ --use-gpus \ - -- ops/pipeline/test-python-wheel.sh gpu + -- ops/pipeline/test-python-wheel.sh --suite gpu --cuda-version 13 * Run Python tests with GPU algorithm on Linux ARM64 @@ -235,7 +235,7 @@ Examples: useful tasks for local development python3 ops/docker_run.py \ --image-uri ${DOCKER_REGISTRY}/xgb-ci.gpu_aarch64:main \ --use-gpus \ - -- ops/pipeline/test-python-wheel.sh gpu-arm64 + -- ops/pipeline/test-python-wheel.sh --suite gpu-arm64 --cuda-version 13 * Run Python tests with GPU algorithm, with multiple GPUs @@ -246,7 +246,7 @@ Examples: useful tasks for local development --image-uri ${DOCKER_REGISTRY}/xgb-ci.gpu:main \ --use-gpus \ --run-args='--shm-size=4g' \ - -- ops/pipeline/test-python-wheel.sh mgpu + -- ops/pipeline/test-python-wheel.sh --suite mgpu --cuda-version 13 # --shm-size=4g is needed for multi-GPU algorithms to function * Build and test JVM packages @@ -503,15 +503,16 @@ For example, when you run ``bash containers/docker_build.sh xgb-ci.gpu``, the lo # docker_build.sh calls docker_build.py... python3 containers/docker_build.py --container-def gpu \ --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ - --build-arg CUDA_VERSION_ARG=12.4.1 --build-arg NCCL_VERSION_ARG=2.23.4-1 \ - --build-arg RAPIDS_VERSION_ARG=24.10 + --build-arg CUDA_VERSION=13.3.0 --build-arg NCCL_VERSION=2.30.7-1 \ + --build-arg RAPIDS_VERSION=26.04 --build-arg ARCH=x86_64 ... # .. and docker_build.py in turn calls "docker build"... - docker build --build-arg CUDA_VERSION_ARG=12.4.1 \ - --build-arg NCCL_VERSION_ARG=2.23.4-1 \ - --build-arg RAPIDS_VERSION_ARG=24.10 \ + docker build --build-arg CUDA_VERSION=13.3.0 \ + --build-arg NCCL_VERSION=2.30.7-1 \ + --build-arg RAPIDS_VERSION=26.04 \ + --build-arg ARCH=x86_64 \ --load --progress=plain \ --ulimit nofile=1024000:1024000 \ -t 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ @@ -527,7 +528,7 @@ Here is an example with ``docker_run.py``: # Run without GPU python3 ops/docker_run.py \ --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.cpu:main \ - -- bash ops/pipeline/build-cpu-impl.sh cpu + -- bash ops/pipeline/test-python-wheel.sh --suite cpu # Run with NVIDIA GPU # Allocate extra space in /dev/shm to enable NCCL @@ -536,26 +537,26 @@ Here is an example with ``docker_run.py``: --image-uri 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ --use-gpus \ --run-args='--shm-size=4g --privileged' \ - -- bash ops/pipeline/test-python-wheel.sh gpu + -- bash ops/pipeline/test-python-wheel.sh --suite mgpu --cuda-version 13 which are translated to the following ``docker run`` invocations: .. code-block:: bash docker run --rm --pid=host \ - -w /workspace -v /path/to/xgboost:/workspace \ + -v /path/to/xgboost:/workspace -w /workspace \ -e CI_BUILD_UID= -e CI_BUILD_USER= \ -e CI_BUILD_GID= -e CI_BUILD_GROUP= \ 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.cpu:main \ - bash ops/pipeline/build-cpu-impl.sh cpu + bash ops/pipeline/test-python-wheel.sh --suite cpu docker run --rm --pid=host --gpus all \ - -w /workspace -v /path/to/xgboost:/workspace \ + -v /path/to/xgboost:/workspace -w /workspace \ -e CI_BUILD_UID= -e CI_BUILD_USER= \ -e CI_BUILD_GID= -e CI_BUILD_GROUP= \ --shm-size=4g --privileged \ 492475357299.dkr.ecr.us-west-2.amazonaws.com/xgb-ci.gpu:main \ - bash ops/pipeline/test-python-wheel.sh gpu + bash ops/pipeline/test-python-wheel.sh --suite mgpu --cuda-version 13 .. _vm_images: From 9cadde52fcfd562557e5953ffb1242938e3627dc Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 10:12:31 +0800 Subject: [PATCH 14/28] Downgrade clang, cleanup the scripts. --- .github/workflows/main.yml | 6 ++-- doc/contrib/coding_guide.rst | 13 +++---- ops/pipeline/build-cuda-clang.sh | 11 +++--- ops/pipeline/run-clang-tidy-clang-cuda.sh | 43 ++--------------------- 4 files changed, 15 insertions(+), 58 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 103500af1f00..30f92a0f4bda 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -141,7 +141,7 @@ jobs: build/testxgboost python-package/dist/*.whl build-cuda-clang: - name: Build CUDA 12.9 with clang 23.1.0.rc2 (x86_64) + name: Build CUDA 12.9 with clang 22.1.8 (x86_64) needs: ci-configure runs-on: - runs-on=${{ github.run_id }} @@ -160,8 +160,8 @@ jobs: submodules: "true" - uses: dmlc/xgboost-devops/actions/sccache@main with: - cache-key-prefix: ${{ github.job }}-clang23rc2-cuda12 - - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 23.1.0.rc2 + cache-key-prefix: ${{ github.job }}-clang22-1-8-cuda12 + - run: bash ops/pipeline/build-cuda-clang.sh --clang-version 22.1.8 - run: sccache --show-stats audit-cuda-wheel: diff --git a/doc/contrib/coding_guide.rst b/doc/contrib/coding_guide.rst index 78b71ae4d36c..a9ece3a0823d 100644 --- a/doc/contrib/coding_guide.rst +++ b/doc/contrib/coding_guide.rst @@ -146,7 +146,7 @@ Linter ====== We use a combination of linters to enforce style convention and find potential errors. Linting is especially useful for scripting languages like Python, as we can catch many errors that would have otherwise occurred at run-time. -For Python scripts, `pylint `_, `black `__ and `isort `__ are used for providing guidance on coding style, and `mypy `__ is required for type checking. The Python formatting and pylint checks are provided via the corresponding pre-commit hooks, which operate on changed files. For C++, `cpplint `_ is used along with ``clang-tidy``. For R, ``lintr`` is used. +For Python scripts, `pylint `_, `ruff `__ are used for providing guidance on coding style, and `mypy `__ is required for type checking. The Python formatting and pylint checks are provided via the corresponding pre-commit hooks, which operate on changed files. For C++, `cpplint `_ is used along with ``clang-tidy``. For R, ``lintr`` is used. To run Python checks locally, install the checkers mentioned previously and run the pre-commit hooks for the files you changed: @@ -198,22 +198,17 @@ scope or adjust the checks: XGBOOST_TIDY_CHECKS='-*,google-runtime-int' \ bash ops/pipeline/run-clang-tidy-clang-cuda.sh -The helper accepts command-line overrides for the build directory, job count, source -filter, checks, extra arguments, and ``warnings-as-errors`` filter. For example: +Use ``--jobs`` to override the number of parallel clang-tidy processes: .. code-block:: bash cd /path/to/xgboost/ - bash ops/pipeline/run-clang-tidy-clang-cuda.sh \ - --build-dir build-clang-tidy-cuda \ - --jobs 16 \ - --source-filter '.*/(src|include)/.*' \ - --checks '-*,google-runtime-int' + bash ops/pipeline/run-clang-tidy-clang-cuda.sh --jobs 16 The helper expects a clang toolchain with ``clang++``, ``clang-linker-wrapper``, and ``run-clang-tidy`` available either from the active conda base environment or from ``XGBOOST_CLANG_PREFIX``. By default, it installs ``clang``, ``clangxx``, and -``clang-tools`` 23.1.0.rc2 from the ``conda-forge/label/llvm_rc`` channel. +``clang-tools`` from the ``conda-forge`` channel. ********************************** Guide for handling user input data diff --git a/ops/pipeline/build-cuda-clang.sh b/ops/pipeline/build-cuda-clang.sh index 6d77b970018b..79f11f642c1a 100755 --- a/ops/pipeline/build-cuda-clang.sh +++ b/ops/pipeline/build-cuda-clang.sh @@ -4,8 +4,7 @@ set -euo pipefail -clang_version="23.1.0.rc2" -clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" +clang_version="22.1.8" cmake_version="4.2.3" build_dir="build-clang-cuda" target="xgboost" @@ -55,9 +54,9 @@ fi if [[ "${XGBOOST_SKIP_CLANG_INSTALL:-0}" != 1 ]]; then clang_packages=( - "${clang_channel}::clang==${clang_version}" - "${clang_channel}::clangxx==${clang_version}" - "${clang_channel}::clang-tools==${clang_version}" + "conda-forge::clang==${clang_version}" + "conda-forge::clangxx==${clang_version}" + "conda-forge::clang-tools==${clang_version}" ) if command -v mamba >/dev/null 2>&1; then mamba install -y -n base -c conda-forge "${clang_packages[@]}" "cmake=${cmake_version}" @@ -100,7 +99,7 @@ echo "--- Build with clang-CUDA using ${clang_cxx}" "${cmake_bin}" --version if ! command -v clang-linker-wrapper >/dev/null 2>&1; then - echo "clang-linker-wrapper is required for clang CUDA offload linking. Install ${clang_channel}::clang-tools==${clang_version}." + echo "clang-linker-wrapper is required for clang CUDA offload linking. Install conda-forge::clang-tools==${clang_version}." exit 1 fi if [[ -f "${clang_bin_dir}/x86_64-conda-linux-gnu-clang++.cfg" ]] && diff --git a/ops/pipeline/run-clang-tidy-clang-cuda.sh b/ops/pipeline/run-clang-tidy-clang-cuda.sh index 1a0c89c62bcf..2a439d10e6da 100755 --- a/ops/pipeline/run-clang-tidy-clang-cuda.sh +++ b/ops/pipeline/run-clang-tidy-clang-cuda.sh @@ -3,11 +3,8 @@ set -euo pipefail -clang_version="23.1.0.rc2" -clang_channel="${XGBOOST_CLANG_CHANNEL:-conda-forge/label/llvm_rc}" -cmake_version="4.2.3" build_dir="build-clang-tidy-cuda" -jobs="${XGBOOST_TIDY_JOBS:-}" +jobs="" checks="${XGBOOST_TIDY_CHECKS:-}" extra_args_csv="${XGBOOST_TIDY_EXTRA_ARGS:--Wno-everything}" files_csv="${XGBOOST_TIDY_FILES:-}" @@ -16,45 +13,13 @@ warnings_as_errors="${XGBOOST_TIDY_WARNINGS_AS_ERRORS:-*,-clang-diagnostic-*,-cl while [[ $# -gt 0 ]]; do case "$1" in - --clang-version) - clang_version="$2" - shift 2 - ;; - --cmake-version) - cmake_version="$2" - shift 2 - ;; - --build-dir) - build_dir="$2" - shift 2 - ;; --jobs) jobs="$2" shift 2 ;; - --checks) - checks="$2" - shift 2 - ;; - --extra-arg) - extra_args_csv="$2" - shift 2 - ;; - --files) - files_csv="$2" - shift 2 - ;; - --source-filter) - source_filter="$2" - shift 2 - ;; - --warnings-as-errors) - warnings_as_errors="$2" - shift 2 - ;; *) echo "Unrecognized argument: $1" - echo "Usage: $0 [--clang-version ] [--cmake-version ] [--build-dir ] [--jobs ] [--checks ] [--extra-arg ] [--files ] [--source-filter ] [--warnings-as-errors ]" + echo "Usage: $0 [--jobs ]" exit 1 ;; esac @@ -79,8 +44,6 @@ if [[ -z "${source_filter}" ]]; then fi "${repo_root}/ops/pipeline/build-cuda-clang.sh" \ - --clang-version "${clang_version}" \ - --cmake-version "${cmake_version}" \ --build-dir "${repo_root}/${build_dir}" \ --configure-only @@ -100,7 +63,7 @@ fi clang_run_tidy="${clang_prefix}/bin/run-clang-tidy" if [[ ! -x "${clang_run_tidy}" ]]; then if ! clang_run_tidy="$(command -v run-clang-tidy)"; then - echo "run-clang-tidy is required. Install ${clang_channel}::clang-tools==${clang_version} or set XGBOOST_CLANG_PREFIX to a clang prefix containing bin/run-clang-tidy." + echo "run-clang-tidy is required. Install conda-forge::clang-tools or set XGBOOST_CLANG_PREFIX to a clang prefix containing bin/run-clang-tidy." exit 1 fi fi From fe33f072ef3e579076f5340601747ac41b94af98 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 10:19:49 +0800 Subject: [PATCH 15/28] More cleanup. --- doc/contrib/coding_guide.rst | 13 ++------- ops/pipeline/run-clang-tidy-clang-cuda.sh | 33 +++-------------------- 2 files changed, 5 insertions(+), 41 deletions(-) diff --git a/doc/contrib/coding_guide.rst b/doc/contrib/coding_guide.rst index a9ece3a0823d..8b0bec2b4a2a 100644 --- a/doc/contrib/coding_guide.rst +++ b/doc/contrib/coding_guide.rst @@ -186,17 +186,8 @@ To run this check locally, use the clang-CUDA helper from the top level source t bash ops/pipeline/run-clang-tidy-clang-cuda.sh This helper configures a clang-generated CUDA compilation database and then runs -``run-clang-tidy -p`` against it. The same path is used by CI. - -By default it lints files under ``src/``. Use environment variables to narrow the -scope or adjust the checks: - -.. code-block:: bash - - cd /path/to/xgboost/ - XGBOOST_TIDY_FILES='src/common/timer.cc,src/predictor/interpretability/shap.cu' \ - XGBOOST_TIDY_CHECKS='-*,google-runtime-int' \ - bash ops/pipeline/run-clang-tidy-clang-cuda.sh +``run-clang-tidy -p`` against files under ``src/`` using the repository's +``.clang-tidy`` configuration. The same path is used by CI. Use ``--jobs`` to override the number of parallel clang-tidy processes: diff --git a/ops/pipeline/run-clang-tidy-clang-cuda.sh b/ops/pipeline/run-clang-tidy-clang-cuda.sh index 2a439d10e6da..623130505abc 100755 --- a/ops/pipeline/run-clang-tidy-clang-cuda.sh +++ b/ops/pipeline/run-clang-tidy-clang-cuda.sh @@ -5,11 +5,6 @@ set -euo pipefail build_dir="build-clang-tidy-cuda" jobs="" -checks="${XGBOOST_TIDY_CHECKS:-}" -extra_args_csv="${XGBOOST_TIDY_EXTRA_ARGS:--Wno-everything}" -files_csv="${XGBOOST_TIDY_FILES:-}" -source_filter="${XGBOOST_TIDY_SOURCE_FILTER:-}" -warnings_as_errors="${XGBOOST_TIDY_WARNINGS_AS_ERRORS:-*,-clang-diagnostic-*,-clang-analyzer-*}" while [[ $# -gt 0 ]]; do case "$1" in @@ -33,15 +28,9 @@ if [[ -z "${jobs}" ]]; then else jobs=4 fi - if (( jobs > 35 )); then - jobs=35 - fi fi repo_root="$(cd "$(dirname "$0")/../.." && pwd)" -if [[ -z "${source_filter}" ]]; then - source_filter="${repo_root}/src/.*" -fi "${repo_root}/ops/pipeline/build-cuda-clang.sh" \ --build-dir "${repo_root}/${build_dir}" \ @@ -68,31 +57,15 @@ if [[ ! -x "${clang_run_tidy}" ]]; then fi fi -IFS=',' read -r -a extra_args <<< "${extra_args_csv}" -IFS=',' read -r -a tidy_files <<< "${files_csv}" - tidy_args=( -p "${repo_root}/${build_dir}" \ -j "${jobs}" \ -config-file "${repo_root}/.clang-tidy" \ -header-filter "${repo_root}/(include|src)/.*" \ - -source-filter "${source_filter}" \ + -source-filter "${repo_root}/src/.*" \ + -extra-arg=-Wno-everything \ + -warnings-as-errors="*,-clang-diagnostic-*,-clang-analyzer-*" \ -quiet ) -if [[ -n "${checks}" ]]; then - tidy_args+=(-checks="${checks}") -fi -if [[ -n "${extra_args_csv}" ]]; then - for extra_arg in "${extra_args[@]}"; do - tidy_args+=(-extra-arg="${extra_arg}") - done -fi -if [[ -n "${warnings_as_errors}" ]]; then - tidy_args+=(-warnings-as-errors="${warnings_as_errors}") -fi -if [[ -n "${files_csv}" ]]; then - tidy_args+=("${tidy_files[@]}") -fi - "${clang_run_tidy}" "${tidy_args[@]}" From f5a9cb5ab0f8813661141f7bae0648271de3ca66 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 11:28:09 +0800 Subject: [PATCH 16/28] Move mgpu tests. --- .github/workflows/main.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 30f92a0f4bda..570164038067 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -350,15 +350,6 @@ jobs: artifact_from: build-cuda12-aarch64 container_options: "--gpus all --privileged" test_args: "" - - cuda_version: 12 - suite: mgpu - arch: x86_64 - runner: linux-amd64-mgpu - image_repo: xgb-ci.gpu_cuda12 - artifact_from: build-cuda12-x86_64 - # mgpu needs --shm-size for NCCL shared memory communication - container_options: "--gpus all --shm-size=4g --privileged" - test_args: "--gtest_filter=*MGPU*" # Default CUDA 13 artifact tests - cuda_version: 13 suite: gpu @@ -376,6 +367,15 @@ jobs: artifact_from: build-cuda13-aarch64 container_options: "--gpus all --privileged" test_args: "" + - cuda_version: 13 + suite: mgpu + arch: x86_64 + runner: linux-amd64-mgpu + image_repo: xgb-ci.gpu + artifact_from: build-cuda13-x86_64 + # mgpu needs --shm-size for NCCL shared memory communication + container_options: "--gpus all --shm-size=4g --privileged" + test_args: "--gtest_filter=*MGPU*" - cuda_version: 13 suite: gpu-rmm arch: x86_64 @@ -425,14 +425,6 @@ jobs: runner: linux-amd64-gpu artifact_from: audit-cuda12-wheel-x86_64 container_options: "--gpus all --privileged" - - cuda_version: 12 - description: Multi-GPU-x86_64-CUDA-12 - image_repo: xgb-ci.gpu_cuda12 - suite: mgpu - runner: linux-amd64-mgpu - artifact_from: audit-cuda12-wheel-x86_64 - # mgpu needs --shm-size for NCCL shared memory communication - container_options: "--gpus all --shm-size=4g --privileged" # xgboost-cu12 aarch64 test using the native CUDA 12.9 runtime - cuda_version: 12 description: GPU-arm64-CUDA-12 @@ -449,6 +441,14 @@ jobs: runner: linux-amd64-gpu artifact_from: audit-cuda13-wheel-x86_64 container_options: "--gpus all --privileged" + - cuda_version: 13 + description: Multi-GPU-x86_64-CUDA-13 + image_repo: xgb-ci.gpu + suite: mgpu + runner: linux-amd64-mgpu + artifact_from: audit-cuda13-wheel-x86_64 + # mgpu needs --shm-size for NCCL shared memory communication + container_options: "--gpus all --shm-size=4g --privileged" - cuda_version: 13 description: GPU-arm64-CUDA-13 image_repo: xgb-ci.gpu_aarch64 From 8cd09caacf1228d2dbd1057d931689e5cf045f22 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 11:35:25 +0800 Subject: [PATCH 17/28] Update JVM. --- jvm-packages/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jvm-packages/pom.xml b/jvm-packages/pom.xml index dd73873aa1fb..eb9a202071bd 100644 --- a/jvm-packages/pom.xml +++ b/jvm-packages/pom.xml @@ -60,9 +60,9 @@ OFF OFF OFF - 24.10.0 - 24.10.0 - cuda12 + 26.04.0 + 26.04.2 + cuda13 3.2.19 2.12.0 false From 2bc9f29fa2cbe3c20406cb7334ffe4e95963c935 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 11:38:26 +0800 Subject: [PATCH 18/28] doc. --- doc/install.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/install.rst b/doc/install.rst index 128759150310..878301c9dc42 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -92,12 +92,14 @@ The default ``xgboost`` wheel for Linux x86_64 and aarch64 is built with CUDA To pip install xgboost -Users whose NVIDIA driver or GPU supports CUDA 12 but not CUDA 13 can instead install the full CUDA 12 package: +Users with GPU whose NVIDIA driver supports CUDA 12 but not CUDA 13 can instead install the CUDA 12 package: .. code-block:: bash pip install xgboost-cu12 +The CUDA 12 package is a driver-compatibility option. + Minimal installation (CPU-only) ******************************* From ecb0c4b45598165c375dd506793b08f6e5363f2f Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 11:44:45 +0800 Subject: [PATCH 19/28] audit. --- ops/pipeline/test-python-wheel.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ops/pipeline/test-python-wheel.sh b/ops/pipeline/test-python-wheel.sh index ce2bdfea7fcb..370ff8754fc3 100755 --- a/ops/pipeline/test-python-wheel.sh +++ b/ops/pipeline/test-python-wheel.sh @@ -89,6 +89,23 @@ export SPARK_TESTING=1 pip install -v ./wheelhouse/*.whl +if [[ -n "${cuda_version}" ]]; then + python - "${cuda_version}" <<'PY' +import sys + +from xgboost import build_info + +expected_cuda_major = int(sys.argv[1]) +cuda_version = build_info()["CUDA_VERSION"] +if cuda_version[0] != expected_cuda_major: + raise RuntimeError( + f"Expected a CUDA {expected_cuda_major} wheel, but it was built with CUDA " + f"{cuda_version[0]}.{cuda_version[1]}" + ) +print(f"Wheel was built with CUDA {cuda_version[0]}.{cuda_version[1]}") +PY +fi + case "$suite" in gpu|gpu-arm64) echo "-- Run Python tests, using a single GPU" From ce56b29e44de08fc8d0c7f414ae3801c683b6bb4 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 12:02:16 +0800 Subject: [PATCH 20/28] float128 with strides. --- src/data/array_interface.h | 7 ++++++- tests/python/test_dmatrix.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/data/array_interface.h b/src/data/array_interface.h index 1b57ed99540d..45d509ae482a 100644 --- a/src/data/array_interface.h +++ b/src/data/array_interface.h @@ -412,7 +412,12 @@ class ArrayInterface { auto typestr = get(array.at("typestr")); this->AssignType(std::string_view{typestr}); ArrayInterfaceHandler::ExtractShape(array, shape); - std::size_t itemsize = typestr[2] - '0'; + std::size_t itemsize = 0; + if (this->type == ArrayInterfaceHandler::kF16) { + itemsize = 16; + } else { + itemsize = typestr[2] - '0'; + } is_contiguous = ArrayInterfaceHandler::ExtractStride(array, itemsize, shape, strides); n = linalg::detail::CalcSize(shape); diff --git a/tests/python/test_dmatrix.py b/tests/python/test_dmatrix.py index cdfae960cf34..871b94bfb0b3 100644 --- a/tests/python/test_dmatrix.py +++ b/tests/python/test_dmatrix.py @@ -81,6 +81,20 @@ def test_np_view(self): assert from_view.shape == from_array.shape assert (from_view == from_array).all() + @pytest.mark.skipif( + np.dtype(np.longdouble).itemsize != 16, + reason="128-bit NumPy floating point is not supported on this platform", + ) + def test_np_float128_view(self): + base = np.arange(1, 401, dtype=np.longdouble).reshape(100, 4) + view = base[:2, ::2] + assert view.strides == (4 * view.itemsize, 2 * view.itemsize) + + dmat = xgb.DMatrix(view) + np.testing.assert_array_equal( + dmat.get_data().toarray(), view.astype(np.float32) + ) + def test_slice(self): X = rng.randn(100, 100) y = rng.randint(low=0, high=3, size=100).astype(np.float32) From dd0421a4f871be10bee901c177a30e6958ea402e Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 12:10:52 +0800 Subject: [PATCH 21/28] disable rmm. --- .../test/scala/ml/dmlc/xgboost4j/scala/spark/GpuTestSuite.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jvm-packages/xgboost4j-spark-gpu/src/test/scala/ml/dmlc/xgboost4j/scala/spark/GpuTestSuite.scala b/jvm-packages/xgboost4j-spark-gpu/src/test/scala/ml/dmlc/xgboost4j/scala/spark/GpuTestSuite.scala index 1bda8f2b18da..407f565f7ed1 100644 --- a/jvm-packages/xgboost4j-spark-gpu/src/test/scala/ml/dmlc/xgboost4j/scala/spark/GpuTestSuite.scala +++ b/jvm-packages/xgboost4j-spark-gpu/src/test/scala/ml/dmlc/xgboost4j/scala/spark/GpuTestSuite.scala @@ -101,7 +101,7 @@ object SparkSessionHolder extends Logging { .config("spark.rapids.sql.test.enabled", "false") .config("spark.stage.maxConsecutiveAttempts", "1") .config("spark.plugins", "com.nvidia.spark.SQLPlugin") - .config("spark.rapids.memory.gpu.pooling.enabled", "false") // Disable RMM for unit tests. + .config("spark.rapids.memory.gpu.pool", "NONE") // Disable RMM for unit tests. .config("spark.sql.files.maxPartitionBytes", "1000") .appName("XGBoost4j-Spark-Gpu unit test") From 9dae8a819a9b68c461396936264257906b137fdc Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 12:38:32 +0800 Subject: [PATCH 22/28] nightly tests. --- ops/pipeline/nightly-test-cccl-impl.sh | 7 ++++++- ops/pipeline/nightly-test-rmm-impl.sh | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ops/pipeline/nightly-test-cccl-impl.sh b/ops/pipeline/nightly-test-cccl-impl.sh index 65e31e901e74..143feca92bad 100755 --- a/ops/pipeline/nightly-test-cccl-impl.sh +++ b/ops/pipeline/nightly-test-cccl-impl.sh @@ -12,10 +12,15 @@ fi cccl_version="$1" # Set up Conda env +cuda_version="$(nvcc --version | awk '/release/ {gsub(/,/, "", $5); print $5}')" +if [[ ! "${cuda_version}" =~ ^[0-9]+\.[0-9]+$ ]]; then + echo "Failed to determine the CUDA version from nvcc: '${cuda_version}'" + exit 1 +fi gosu root chown -R $(id -u):$(id -g) /opt/miniforge/envs /opt/miniforge/pkgs/cache gosu root chown $(id -u):$(id -g) /opt/miniforge/pkgs mamba create -y -n cccl_test -c conda-forge python=3.13 \ - cuda-version=13.0 cxx-compiler cuda-cudart-dev cuda-nvcc gcc_linux-64=14.* ninja \ + "cuda-version=${cuda_version}" cxx-compiler cuda-cudart-dev cuda-nvcc gcc_linux-64=14.* ninja \ gtest nccl source activate cccl_test diff --git a/ops/pipeline/nightly-test-rmm-impl.sh b/ops/pipeline/nightly-test-rmm-impl.sh index e4a38b113a28..1a7dde09d545 100755 --- a/ops/pipeline/nightly-test-rmm-impl.sh +++ b/ops/pipeline/nightly-test-rmm-impl.sh @@ -12,10 +12,15 @@ fi rmm_version="$1" # Set up Conda env +cuda_version="$(nvcc --version | awk '/release/ {gsub(/,/, "", $5); print $5}')" +if [[ ! "${cuda_version}" =~ ^[0-9]+\.[0-9]+$ ]]; then + echo "Failed to determine the CUDA version from nvcc: '${cuda_version}'" + exit 1 +fi gosu root chown -R $(id -u):$(id -g) /opt/miniforge/envs /opt/miniforge/pkgs/cache gosu root chown $(id -u):$(id -g) /opt/miniforge/pkgs mamba create -y -n rmm_test -c conda-forge -c rapidsai-nightly python=3.13 \ - cuda-version=13.0 cxx-compiler cuda-cudart-dev cuda-nvcc gcc_linux-64=14.* ninja \ + "cuda-version=${cuda_version}" cxx-compiler cuda-cudart-dev cuda-nvcc gcc_linux-64=14.* ninja \ gtest nccl "rmm=${rmm_version%.*}.*,>=0.0.0a0" source activate rmm_test From 9f00ea99009ba0ee0cedd63e179f3d028b13a163 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 13:26:02 +0800 Subject: [PATCH 23/28] polars. --- tests/python/test_with_polars.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/python/test_with_polars.py b/tests/python/test_with_polars.py index b79cbafc545c..982c45169991 100644 --- a/tests/python/test_with_polars.py +++ b/tests/python/test_with_polars.py @@ -47,7 +47,9 @@ def test_polars_basic( df = pl.DataFrame({"a": [True, False, False], "b": [False, False, True]}) Xy = DMatrixT(df) - np.testing.assert_equal(Xy.get_data().data, np.array([1, m, m, m, m, 1])) + np.testing.assert_equal( + Xy.get_data().data, np.array([1.0, m, m, m, m, 1.0], dtype=np.float32) + ) def test_polars_missing() -> None: From c33618c901ea95111f550ae1e5c2952ae7dab957 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 17:13:33 +0800 Subject: [PATCH 24/28] doc. --- doc/install.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/install.rst b/doc/install.rst index 878301c9dc42..28e1719f996d 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -96,6 +96,7 @@ Users with GPU whose NVIDIA driver supports CUDA 12 but not CUDA 13 can instead .. code-block:: bash + pip uninstall xgboost xgboost-cu12 pip install xgboost-cu12 The CUDA 12 package is a driver-compatibility option. From 77cb0801540670711c22c15c14ea98b088fe36e4 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 22:11:55 +0800 Subject: [PATCH 25/28] Update document. --- doc/gpu/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gpu/index.rst b/doc/gpu/index.rst index d6c4fcde4a63..3e012671391b 100644 --- a/doc/gpu/index.rst +++ b/doc/gpu/index.rst @@ -4,7 +4,7 @@ XGBoost GPU Support This page contains information about GPU algorithms supported in XGBoost. -.. note:: CUDA 12.0, Compute Capability 5.0 required (See `this list `_ to look up compute capability of your GPU card.) +.. note:: CUDA >= 12.9 is required. ********************************************* CUDA Accelerated Tree Construction Algorithms From 52ade8254f1c283fb1514773c8fc5a3bbf00d8eb Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 22:21:12 +0800 Subject: [PATCH 26/28] Update & fix documents. --- doc/build.rst | 20 +------------------- doc/gpu/index.rst | 2 +- doc/install.rst | 2 ++ plugin/federated/README.md | 18 +++++++++++++----- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/doc/build.rst b/doc/build.rst index 5ec1269c003c..20d6f21c059e 100644 --- a/doc/build.rst +++ b/doc/build.rst @@ -139,23 +139,6 @@ architectures can be found `in this page `_. Alternatively, one can use the -``libgrpc`` and the ``protobuf`` package from conda forge if conda is available. After -obtaining the required dependencies, enable the flag: ``-DPLUGIN_FEDERATED=ON`` when -running CMake. Please note that only Linux is supported for the federated plugin. - - -.. code-block:: bash - - cmake -B build -S . -DPLUGIN_FEDERATED=ON -GNinja - cd build && ninja - - .. _build_python: *********************************** @@ -206,8 +189,7 @@ There are several ways to build and install the package from source: --config-settings cmake.define.USE_CUDA=ON \ --config-settings cmake.define.USE_NCCL=ON - Common CMake options - (see :ref:`building-the-shared-library` for the full list): + Common CMake options (see :ref:`build_shared_lib` for the full list): - ``USE_CUDA`` — build with CUDA / GPU acceleration - ``USE_NCCL`` — build with NCCL for distributed GPU training diff --git a/doc/gpu/index.rst b/doc/gpu/index.rst index 3e012671391b..71d3ad36cf24 100644 --- a/doc/gpu/index.rst +++ b/doc/gpu/index.rst @@ -4,7 +4,7 @@ XGBoost GPU Support This page contains information about GPU algorithms supported in XGBoost. -.. note:: CUDA >= 12.9 is required. +.. note:: CUDA >= 12.9 is required. See :ref:`wheel-cuda`. ********************************************* CUDA Accelerated Tree Construction Algorithms diff --git a/doc/install.rst b/doc/install.rst index 28e1719f996d..03a4799c5d12 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -84,6 +84,8 @@ modern Jetson or Graviton machines provides the same GPU functionality as the Linux x86_64 wheel. Multi-node and multi-GPU training remain experimental on ARM64 at this time. +.. _wheel-cuda: + CUDA toolkit variants (Linux) ***************************** The default ``xgboost`` wheel for Linux x86_64 and aarch64 is built with CUDA Toolkit 13.x: diff --git a/plugin/federated/README.md b/plugin/federated/README.md index 1040c933ef12..d048822ef18f 100644 --- a/plugin/federated/README.md +++ b/plugin/federated/README.md @@ -3,14 +3,22 @@ XGBoost Plugin for Federated Learning This folder contains the plugin for federated learning. -See [build instruction](../../doc/build.rst) for how to build the plugin. +Build +----- +The federated learning plugin requires `grpc` and `protobuf`. To install grpc, refer to the [installation guide from the gRPC website](https://grpc.io/docs/languages/cpp/quickstart/). Alternatively, one can use the `libgrpc` and the `protobuf` package from conda forge if conda is available. After obtaining the required dependencies, enable the flag: `-DPLUGIN_FEDERATED=ON` when running CMake. Please note that only Linux is supported for the federated plugin. + +``` shell + +cmake -B build -S . -DPLUGIN_FEDERATED=ON -GNinja +cd build && ninja + +``` Test Federated XGBoost ---------------------- -```shell + +``` shell # Under xgboost source tree. -cd tests/distributed/test_federated -# This tests both CPU training (`hist`) and GPU training (`gpu_hist`). -./runtests-federated.sh +pytest -sv tests/test_distributed/test_federated ``` From 736c54f38a2fbb9f8972e7647b1cc624fcd10f60 Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 22:27:11 +0800 Subject: [PATCH 27/28] Cleanup the installation doc. --- doc/install.rst | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/doc/install.rst b/doc/install.rst index 03a4799c5d12..acf524f7d506 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -16,35 +16,14 @@ Stable Release Python ------ -Pre-built binary wheels are uploaded to PyPI (Python Package Index) for each release. Supported platforms are Linux (x86_64, aarch64), Windows (x86_64) and MacOS (x86_64, Apple Silicon). +Pre-built binary wheels are uploaded to PyPI (Python Package Index) for each release. Supported platforms are Linux (x86_64, aarch64), Windows (x86_64) and MacOS (x86_64, Apple Silicon). In addition the ``xgboost-cpu`` windows package supports aarch64. .. code-block:: bash - # Pip 21.3+ is required pip install xgboost -You might need to run the command with ``--user`` flag or use ``virtualenv`` if you run -into permission errors. - -.. note:: Parts of the Python package now require glibc 2.28+ - - Starting from 2.1.0, XGBoost Python package will be distributed in two variants: - - * ``manylinux_2_28``: for recent Linux distros with glibc 2.28 or newer. This variant supports GPU algorithms. - * ``manylinux2014``: for old Linux distros with glibc older than 2.28. This variant does not support GPU algorithms or federated learning. - - The ``pip`` package manager will automatically choose the correct variant depending on your system. - - Starting from **May 31, 2025**, we will stop distributing the ``manylinux2014`` variant and exclusively - distribute the ``manylinux_2_28`` variant. We made this decision so that our CI/CD pipeline won't have - depend on software components that reached end-of-life (such as CentOS 7). We strongly encourage - everyone to migrate to recent Linux distros in order to use future versions of XGBoost. - - Note. If you want to use GPU algorithms on an older Linux distro, you have two alternatives: - - 1. Upgrade to a recent Linux distro with glibc 2.28+. OR - 2. Build XGBoost from the source. +You might need to run the command with ``--user`` flag or use ``virtualenv`` if you run into permission errors. .. note:: Windows users need to install Visual C++ Redistributable @@ -55,11 +34,6 @@ into permission errors. necessary libraries and thus don't need to install Visual C++ Redistributable. - -.. note:: - - Federated learning has been removed from PyPI binary wheels since 3.4 - Capabilities of binary wheels for each platform: .. |tick| unicode:: U+2714 @@ -78,6 +52,8 @@ Capabilities of binary wheels for each platform: +---------------------+---------+----------------------+ | Windows | |tick| | |cross| | +---------------------+---------+----------------------+ +| Windows aarch64 | |cross| | |cross| | ++---------------------+---------+----------------------+ Linux aarch64 wheels now ship with CUDA support, so ``pip install xgboost`` on modern Jetson or Graviton machines provides the same GPU functionality as the From c5720bc519e4c29492e43e230dd4c96d460a27fc Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Fri, 31 Jul 2026 22:42:11 +0800 Subject: [PATCH 28/28] tag. --- ops/pipeline/get-image-tag.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ops/pipeline/get-image-tag.sh b/ops/pipeline/get-image-tag.sh index 334cab33652f..c69e7607dfd8 100755 --- a/ops/pipeline/get-image-tag.sh +++ b/ops/pipeline/get-image-tag.sh @@ -7,4 +7,4 @@ # or PR number: # IMAGE_TAG=PR-88 -IMAGE_TAG=PR-97 +IMAGE_TAG=main