From a4a67217a874676086b151a8b849a8dd7aecf721 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Sun, 12 Jan 2025 21:46:32 -0500 Subject: [PATCH] add cuda-python pure Python wheel --- .github/workflows/build-and-test.yml | 61 ++++++++++++++++++++++++---- cuda_bindings/pyproject.toml | 2 +- cuda_python/LICENSE | 1 + cuda_python/README.md | 1 + cuda_python/pyproject.toml | 41 +++++++++++++++++++ cuda_python/setup.py | 20 +++++++++ 6 files changed, 116 insertions(+), 10 deletions(-) create mode 120000 cuda_python/LICENSE create mode 120000 cuda_python/README.md create mode 100644 cuda_python/pyproject.toml create mode 100644 cuda_python/setup.py diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 42bf1563..a809567f 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -42,6 +42,9 @@ jobs: # (matrix.host-platform == 'win-64' && 'windows-amd64-cpu8') }} outputs: BUILD_CTK_VER: ${{ steps.pass_env.outputs.CUDA_VERSION }} + defaults: + run: + shell: bash --noprofile --norc -xeuo pipefail {0} steps: - name: Checkout ${{ github.event.repository.name }} uses: actions/checkout@v4 @@ -63,7 +66,6 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: Set environment variables - shell: bash --noprofile --norc -xeuo pipefail {0} run: | PYTHON_VERSION_FORMATTED=$(echo '${{ matrix.python-version }}' | tr -d '.') if [[ "${{ matrix.host-platform }}" == linux* ]]; then @@ -81,7 +83,6 @@ jobs: echo "CIBW_BUILD=${CIBW_BUILD}" >> $GITHUB_ENV - name: Dump environment - shell: bash --noprofile --norc -xeuo pipefail {0} run: | env @@ -110,7 +111,6 @@ jobs: output-dir: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }} - name: List the cuda.bindings artifacts directory - shell: bash --noprofile --norc -xeuo pipefail {0} run: | if [[ "${{ matrix.host-platform }}" == win* ]]; then export CHOWN=chown @@ -122,8 +122,8 @@ jobs: # TODO: enable this after NVIDIA/cuda-python#297 is resolved # - name: Check cuda.bindings wheel - # shell: bash --noprofile --norc -xeuo pipefail {0} # run: | + # pip install twine # twine check ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl - name: Upload cuda.bindings build artifacts @@ -132,7 +132,36 @@ jobs: name: ${{ env.CUDA_BINDINGS_ARTIFACT_NAME }} path: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl if-no-files-found: error - overwrite: 'true' + + # upload-artifact's "overwrite: true" option has a race condition among parallel + # jobs, so we let job 0 do the work + - name: Build and check cuda-python wheel + if: ${{ strategy.job-index == 0 }} + run: | + pushd cuda_python + pip wheel -v --no-deps . + pip install twine # TODO: remove me (see above) + twine check *.whl + popd + + - name: List the cuda-python artifacts directory + if: ${{ strategy.job-index == 0 }} + run: | + if [[ "${{ matrix.host-platform }}" == win* ]]; then + export CHOWN=chown + else + export CHOWN="sudo chown" + fi + $CHOWN -R $(whoami) cuda_python/*.whl + ls -lahR cuda_python + + - name: Upload cuda-python build artifacts + if: ${{ strategy.job-index == 0 }} + uses: actions/upload-artifact@v4 + with: + name: cuda-python-wheel + path: cuda_python/*.whl + if-no-files-found: error - name: Pass environment variables to the next runner id: pass_env @@ -186,9 +215,11 @@ jobs: NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} needs: - build + defaults: + run: + shell: bash --noprofile --norc -xeuo pipefail {0} steps: - name: Ensure GPU is working - shell: bash --noprofile --norc -xeuo pipefail {0} run: nvidia-smi - name: Checkout ${{ github.event.repository.name }} @@ -198,7 +229,6 @@ jobs: ref: ${{ github.head_ref || github.ref_name }} - name: Set environment variables - shell: bash --noprofile --norc -xeuo pipefail {0} run: | PYTHON_VERSION_FORMATTED=$(echo '${{ matrix.python-version }}' | tr -d '.') if [[ "${{ matrix.host-platform }}" == linux* ]]; then @@ -221,6 +251,17 @@ jobs: echo "CUDA_BINDINGS_ARTIFACTS_DIR=$(realpath "$REPO_DIR/cuda_bindings/dist")" >> $GITHUB_ENV echo "SKIP_CUDA_BINDINGS_TEST=${SKIP_CUDA_BINDINGS_TEST}" >> $GITHUB_ENV + - name: Download cuda-python build artifacts + uses: actions/download-artifact@v4 + with: + name: cuda-python-wheel + path: . + + - name: Display structure of downloaded cuda-python artifacts + run: | + pwd + ls -lahR . + - name: Download cuda.bindings build artifacts uses: actions/download-artifact@v4 with: @@ -228,7 +269,6 @@ jobs: path: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }} - name: Display structure of downloaded cuda.bindings artifacts - shell: bash --noprofile --norc -xeuo pipefail {0} run: | pwd ls -lahR $CUDA_BINDINGS_ARTIFACTS_DIR @@ -251,7 +291,6 @@ jobs: - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} - shell: bash --noprofile --norc -xeuo pipefail {0} run: | pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}" if [[ "${{ matrix.local-ctk }}" == 1 ]]; then @@ -280,6 +319,10 @@ jobs: fi popd + - name: Ensure cuda-python installable + run: | + pip install cuda_python*.whl + checks: name: Check job status permissions: diff --git a/cuda_bindings/pyproject.toml b/cuda_bindings/pyproject.toml index b3f982fd..0abf0672 100644 --- a/cuda_bindings/pyproject.toml +++ b/cuda_bindings/pyproject.toml @@ -11,7 +11,7 @@ requires = ["setuptools", "cython", "pyclibrary"] build-backend = "setuptools.build_meta" [project] -name = "cuda-python" +name = "cuda-bindings" description = "Python bindings for CUDA" authors = [{name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com"},] license = {file = "LICENSE"} diff --git a/cuda_python/LICENSE b/cuda_python/LICENSE new file mode 120000 index 00000000..ea5b6064 --- /dev/null +++ b/cuda_python/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/cuda_python/README.md b/cuda_python/README.md new file mode 120000 index 00000000..32d46ee8 --- /dev/null +++ b/cuda_python/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/cuda_python/pyproject.toml b/cuda_python/pyproject.toml new file mode 100644 index 00000000..93c68abc --- /dev/null +++ b/cuda_python/pyproject.toml @@ -0,0 +1,41 @@ +# Copyright 2023-2025 NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +[build-system] +requires = ["setuptools",] +build-backend = "setuptools.build_meta" + +[project] +name = "cuda-python" +description = "CUDA Python: Performance meets Productivity" +readme = {file = "README.md", content-type = "text/markdown"} +authors = [{name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com"},] +license = {file = "LICENSE"} +classifiers = [ + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries", + "Topic :: Education", + "Topic :: Scientific/Engineering", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Intended Audience :: End Users/Desktop", + "License :: Other/Proprietary License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: Implementation :: CPython", + "Environment :: GPU :: NVIDIA CUDA", + "Environment :: GPU :: NVIDIA CUDA :: 12", +] +dynamic = ["version", "dependencies"] + +[project.urls] +homepage = "https://nvidia.github.io/cuda-python/" +documentation = "https://nvidia.github.io/cuda-python/" +repository = "https://github.com/NVIDIA/cuda-python/" +issues = "https://github.com/NVIDIA/cuda-python/issues/" diff --git a/cuda_python/setup.py b/cuda_python/setup.py new file mode 100644 index 00000000..3c422f91 --- /dev/null +++ b/cuda_python/setup.py @@ -0,0 +1,20 @@ +# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED. +# +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +from setuptools import setup + +# We want to keep the version in sync with cuda.bindings, but setuptools would not let +# us to refer to any files outside of the project root, so we have to employ our own +# run-time lookup using setup()... +with open("../cuda_bindings/cuda/bindings/_version.py") as f: + exec(f.read()) +version = __version__ # noqa: F821 +del __version__ # noqa: F821 + +setup( + version=version, + install_requires=[ + f"cuda-bindings~={version}", + ], +)