From 3220b2689c5f60b51ef6c5b673124920cc98e201 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 14 Aug 2026 02:52:09 -0700 Subject: [PATCH] CI: Add native Windows ARM64 testing --- .github/actionlint.yaml | 1 + .github/workflows/build-wheel.yml | 33 +++-- .github/workflows/ci.yml | 28 +++- .github/workflows/test-wheel-windows.yml | 166 ++++++++++++++++++++++- ci/test-matrix.yml | 5 +- ci/tools/run-tests | 12 +- 6 files changed, 219 insertions(+), 26 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index db23ece3410..138ecbde44b 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -8,3 +8,4 @@ self-hosted-runner: labels: - linux-amd64-cpu8 - linux-amd64-gpu-l4-latest-1 + - windows-arm64-1xgb10 diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index c71fdf46af5..50f66364ce1 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -51,6 +51,11 @@ on: required: false type: boolean default: true + test-python-version: + description: "Build compiled test artifacts only for this Python version; empty means all" + required: false + type: string + default: "" baseline-run-id: required: false type: string @@ -79,6 +84,8 @@ jobs: (inputs.host-platform == 'linux-aarch64' && 'linux-arm64-cpu8') || (inputs.host-platform == 'win-64' && 'windows-2022') || (inputs.host-platform == 'win-arm64' && 'windows-11-arm') }} + env: + BUILD_TEST_ARTIFACTS: ${{ inputs.test-python-version == '' || matrix.python-version == inputs.test-python-version }} steps: - name: Checkout ${{ github.event.repository.name }} uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -485,7 +492,7 @@ jobs: - name: Set up Python id: setup-python2 - if: ${{ !inputs.single-cuda-major && (inputs.test-bindings || inputs.test-core) }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && (inputs.test-bindings || inputs.test-core) }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} @@ -494,17 +501,17 @@ jobs: allow-prereleases: ${{ startsWith(matrix.python-version, '3.15') }} - name: Enable Scientific Python Nightly Wheels for Python 3.15 - if: ${{ !inputs.single-cuda-major && (inputs.test-bindings || inputs.test-core) && startsWith(matrix.python-version, '3.15') }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && (inputs.test-bindings || inputs.test-core) && startsWith(matrix.python-version, '3.15') }} run: | echo "PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" >> "$GITHUB_ENV" echo "PIP_ONLY_BINARY=numpy" >> "$GITHUB_ENV" - name: verify free-threaded build - if: ${{ !inputs.single-cuda-major && (inputs.test-bindings || inputs.test-core) && endsWith(matrix.python-version, 't') }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && (inputs.test-bindings || inputs.test-core) && endsWith(matrix.python-version, 't') }} run: python -c 'import sys; assert not sys._is_gil_enabled()' - name: Set up Python include paths - if: ${{ !inputs.single-cuda-major && (inputs.test-bindings || inputs.test-core) }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && (inputs.test-bindings || inputs.test-core) }} run: | if [[ "${{ inputs.host-platform }}" == linux* ]]; then echo "CPLUS_INCLUDE_PATH=${Python3_ROOT_DIR}/include/python${{ matrix.python-version }}" >> $GITHUB_ENV @@ -515,19 +522,19 @@ jobs: echo "PY_EXT_SUFFIX=$(python -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))")" >> $GITHUB_ENV - name: Install cuda.pathfinder (required for next step) - if: ${{ !inputs.single-cuda-major && (inputs.test-bindings || inputs.test-core) }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && (inputs.test-bindings || inputs.test-core) }} run: | pip install cuda_pathfinder/*.whl - name: Hide GNU link.exe so Meson finds MSVC link.exe - if: ${{ !inputs.single-cuda-major && startsWith(inputs.host-platform, 'win') && (inputs.test-bindings || inputs.test-core) }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && startsWith(inputs.host-platform, 'win') && (inputs.test-bindings || inputs.test-core) }} run: | if [ -f "/c/Program Files/Git/usr/bin/link.exe" ]; then mv "/c/Program Files/Git/usr/bin/link.exe" "/c/Program Files/Git/usr/bin/link.exe.bak" fi - name: Build cuda.bindings Cython tests - if: ${{ !inputs.single-cuda-major && inputs.test-bindings }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-bindings }} run: | pip install ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl --group ./cuda_bindings/pyproject.toml:test pushd ${{ env.CUDA_BINDINGS_CYTHON_TESTS_DIR }} @@ -535,7 +542,7 @@ jobs: popd - name: Upload cuda.bindings Cython tests - if: ${{ !inputs.single-cuda-major && inputs.test-bindings }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-bindings }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ env.CUDA_BINDINGS_ARTIFACT_NAME }}-tests @@ -543,10 +550,10 @@ jobs: if-no-files-found: error - name: Build cuda.core Cython tests - if: ${{ !inputs.single-cuda-major && inputs.test-core }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-core }} run: | pip install ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl - if ${{ inputs.build-core }}; then + if ${{ inputs.build-core && !inputs.single-cuda-major }}; then core_wheel=$(find "${{ env.CUDA_CORE_ARTIFACTS_DIR }}/cu${BUILD_CUDA_MAJOR}" -maxdepth 1 -type f -name '*.whl' -print -quit) else core_wheel=$(find "${{ env.CUDA_CORE_ARTIFACTS_DIR }}" -maxdepth 1 -type f -name '*.whl' -print -quit) @@ -561,7 +568,7 @@ jobs: popd - name: Upload cuda.core Cython tests - if: ${{ !inputs.single-cuda-major && inputs.test-core }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-core }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ env.CUDA_CORE_ARTIFACT_NAME }}-tests @@ -579,13 +586,13 @@ jobs: cuda-path: "./cuda_toolkit_prev" - name: Build cuda.core test binaries - if: ${{ !inputs.single-cuda-major && inputs.test-core }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-core }} run: | nvcc --version python "${{ env.CUDA_CORE_TEST_BINARIES_DIR }}/build_test_binaries.py" - name: Upload cuda.core test binaries - if: ${{ !inputs.single-cuda-major && inputs.test-core }} + if: ${{ env.BUILD_TEST_ARTIFACTS == 'true' && inputs.test-core }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ env.CUDA_CORE_ARTIFACT_NAME }}-test-binaries diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8eabf30e4fb..f5d1c7c3aa3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -424,6 +424,7 @@ jobs: cuda-channel: ${{ needs.ci-vars.outputs.CUDA_BUILD_CHANNEL }} prev-cuda-version: ${{ needs.ci-vars.outputs.CUDA_PREV_BUILD_VER }} single-cuda-major: true + test-python-version: '3.13' # NOTE: test-sdist jobs are split by platform (mirroring build-* and test-wheel-*) # so platform-specific sources (e.g. cuda_bindings/*_windows.pyx selected by @@ -538,6 +539,25 @@ jobs: nruns: ${{ (github.event_name == 'schedule' && 5) || 1}} test-bindings: ${{ fromJSON(needs.detect-changes.outputs.test_bindings) }} + test-windows-arm64: + name: Test win-arm64 + if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.doc-only) && needs.ci-vars.outputs.CUDA_BUILD_CHANNEL == 'prerelease' }} + permissions: + actions: read + contents: read # This is required for actions/checkout + needs: + - ci-vars + - should-skip + - build-linux-64 + - build-windows-arm64 + uses: ./.github/workflows/test-wheel-windows.yml + with: + build-type: pull-request + host-platform: win-arm64 + build-ctk-ver: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }} + build-ctk-channel: ${{ needs.ci-vars.outputs.CUDA_BUILD_CHANNEL }} + test-bindings-ptds: true + doc: name: Docs if: ${{ github.repository_owner == 'nvidia' }} @@ -601,6 +621,7 @@ jobs: - test-linux-64 - test-linux-aarch64 - test-windows + - test-windows-arm64 - doc - precommit-windows steps: @@ -639,12 +660,12 @@ jobs: check_result "doc" "success" "${{ needs.doc.result }}" check_result "precommit-windows" "success" "${{ needs.precommit-windows.result }}" - # [doc-only] skips all builds and tests. Windows preview wheel builds - # run, but GPU tests remain skipped until suitable runners are available. + # [doc-only] skips all builds and tests. if [[ "$doc_only" == "true" ]]; then linux_expected="skipped" windows_build_expected="skipped" windows_arm_build_expected="skipped" + windows_arm_test_expected="skipped" windows_sdist_expected="skipped" windows_test_expected="skipped" else @@ -653,14 +674,17 @@ jobs: windows_sdist_expected="success" if [[ "$cuda_build_channel" == "prerelease" ]]; then windows_arm_build_expected="success" + windows_arm_test_expected="success" windows_test_expected="skipped" else windows_arm_build_expected="skipped" + windows_arm_test_expected="skipped" windows_test_expected="success" fi fi check_result "build-windows" "$windows_build_expected" "${{ needs.build-windows.result }}" check_result "build-windows-arm64" "$windows_arm_build_expected" "${{ needs.build-windows-arm64.result }}" + check_result "test-windows-arm64" "$windows_arm_test_expected" "${{ needs.test-windows-arm64.result }}" check_result "test-sdist-linux" "$linux_expected" "${{ needs.test-sdist-linux.result }}" check_result "test-sdist-windows" "$windows_sdist_expected" "${{ needs.test-sdist-windows.result }}" check_result "test-linux-64" "$linux_expected" "${{ needs.test-linux-64.result }}" diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 04b290b1cd0..6c42787050e 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -16,6 +16,9 @@ on: build-ctk-ver: type: string required: true + build-ctk-channel: + type: string + default: stable matrix_filter: type: string default: "." @@ -28,6 +31,10 @@ on: test-bindings: type: boolean default: true + test-bindings-ptds: + description: Run cuda.bindings tests with the per-thread default stream too + type: boolean + default: false test-core: type: boolean default: true @@ -62,7 +69,8 @@ jobs: shell: bash --noprofile --norc -xeuo pipefail {0} env: BUILD_TYPE: ${{ inputs.build-type }} - ARCH: ${{ (inputs.host-platform == 'win-64' && 'amd64') }} + ARCH: ${{ (inputs.host-platform == 'win-64' && 'amd64') || + (inputs.host-platform == 'win-arm64' && 'arm64') }} outputs: MATRIX: ${{ steps.compute-matrix.outputs.MATRIX }} steps: @@ -96,8 +104,8 @@ jobs: echo "MATRIX=${MATRIX}" | tee --append "${GITHUB_OUTPUT}" test: - name: Python ${{ matrix.PY_VER }}, CUDA ${{ matrix.CUDA_VER }} (${{ (matrix.LOCAL_CTK == '1' && 'local') || 'wheels' }}), GPU ${{ matrix.GPU }}${{ matrix.GPU_COUNT != '1' && format(' (x{0})', matrix.GPU_COUNT) || '' }} (${{ matrix.DRIVER_MODE }})${{ matrix.ENV.TORCH_VER && format(', {0}+{1}', matrix.ENV.TORCH_VER, matrix.ENV.TORCH_CUDA) || '' }}${{ matrix.ENV.MODE == 'nightly-numba-cuda' && ', latest' || '' }} - timeout-minutes: 60 + name: Python ${{ matrix.PY_VER }}, CUDA ${{ matrix.CUDA_VER }} (${{ (matrix.LOCAL_CTK == '1' && 'local') || 'wheels' }}), GPU ${{ matrix.GPU }}${{ matrix.GPU_COUNT != '1' && format(' (x{0})', matrix.GPU_COUNT) || '' }}${{ matrix.DRIVER_MODE && format(' ({0})', matrix.DRIVER_MODE) || '' }}${{ matrix.ENV.TORCH_VER && format(', {0}+{1}', matrix.ENV.TORCH_VER, matrix.ENV.TORCH_CUDA) || '' }}${{ matrix.ENV.MODE == 'nightly-numba-cuda' && ', latest' || '' }} + timeout-minutes: ${{ (inputs.host-platform == 'win-arm64' && 120) || 60 }} # The build stage could fail but we want the CI to keep moving. needs: compute-matrix strategy: @@ -106,19 +114,114 @@ jobs: if: ${{ github.repository_owner == 'nvidia' && !cancelled() }} # TODO: remove continue-on-error once 3.15 is officially supported continue-on-error: ${{ startsWith(matrix.PY_VER, '3.15') }} - runs-on: "windows-${{ matrix.ARCH }}-gpu-${{ matrix.GPU }}-${{ matrix.RUNNER_DRIVER }}-${{ matrix.GPU_COUNT }}" + runs-on: ${{ matrix.RUNNER || format('windows-{0}-gpu-{1}-{2}-{3}', matrix.ARCH, matrix.GPU, matrix.RUNNER_DRIVER, matrix.GPU_COUNT) }} steps: + - name: Set up Git Bash and 7-Zip for Windows ARM64 + if: ${{ inputs.host-platform == 'win-arm64' }} + timeout-minutes: 10 + shell: powershell + env: + PORTABLE_GIT_VERSION: '2.55.0.3' + PORTABLE_GIT_URL: https://github.com/git-for-windows/git/releases/download/v2.55.0.windows.3/PortableGit-2.55.0.3-arm64.7z.exe + PORTABLE_GIT_SHA256: 3bf26b94d9399b16a890776e468334f501742861576cbcdea2d9134643c374bd + SEVEN_ZIP_URL: https://github.com/ip7z/7zip/releases/download/26.02/7zr.exe + SEVEN_ZIP_SHA256: 56b8cc9f4971cef253644fafe54063ed7fdca551d4dee0f8c6baa81b855acd72 + run: | + if (-not $env:RUNNER_TEMP) { + throw "RUNNER_TEMP is not set." + } + + # Keep executables job-local: later PR steps must not be able to + # poison a persistent tool cache for the next run. + $sevenZipRoot = Join-Path $env:RUNNER_TEMP "7-Zip-26.02" + if (Test-Path $sevenZipRoot) { + Remove-Item -Recurse -Force $sevenZipRoot + } + New-Item -ItemType Directory -Force -Path $sevenZipRoot | Out-Null + $sevenZip = Join-Path $sevenZipRoot "7z.exe" + Invoke-WebRequest -UseBasicParsing -Uri $env:SEVEN_ZIP_URL -OutFile $sevenZip + $actualHash = (Get-FileHash -Path $sevenZip -Algorithm SHA256).Hash.ToLowerInvariant() + if ($actualHash -ne $env:SEVEN_ZIP_SHA256) { + throw "7-Zip checksum mismatch: expected $env:SEVEN_ZIP_SHA256, got $actualHash." + } + + $gitRoot = Join-Path $env:RUNNER_TEMP "PortableGit-$env:PORTABLE_GIT_VERSION-arm64" + $git = Join-Path $gitRoot "cmd\git.exe" + $bash = Join-Path $gitRoot "bin\bash.exe" + $archive = Join-Path $env:RUNNER_TEMP "PortableGit-$env:PORTABLE_GIT_VERSION-arm64.7z.exe" + Invoke-WebRequest -UseBasicParsing -Uri $env:PORTABLE_GIT_URL -OutFile $archive + $actualHash = (Get-FileHash -Path $archive -Algorithm SHA256).Hash.ToLowerInvariant() + if ($actualHash -ne $env:PORTABLE_GIT_SHA256) { + throw "PortableGit checksum mismatch: expected $env:PORTABLE_GIT_SHA256, got $actualHash." + } + + if (Test-Path $gitRoot) { + Remove-Item -Recurse -Force $gitRoot + } + New-Item -ItemType Directory -Force -Path $gitRoot | Out-Null + & $sevenZip x -y $archive "-o$gitRoot" + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item -Force $archive + + $postInstall = Join-Path $gitRoot "post-install.bat" + if (-not (Test-Path $postInstall)) { + throw "PortableGit post-install.bat was not found after extraction." + } + Push-Location $gitRoot + try { + & $postInstall + if ($LASTEXITCODE -ne 0) { + throw "PortableGit post-install.bat exited with code $LASTEXITCODE." + } + } + finally { + Pop-Location + } + + if (-not ((Test-Path $git) -and (Test-Path $bash))) { + throw "Git Bash was not found after extracting PortableGit." + } + + $gitInfo = & $git version --build-options | Out-String + $gitExitCode = $LASTEXITCODE + Write-Host $gitInfo + if ($gitExitCode -ne 0 -or $gitInfo -notmatch '(?im)^cpu: (arm64|aarch64)\s*$') { + throw "PortableGit is not a native ARM64 build." + } + # Git for Windows does not yet ship its POSIX layer natively on ARM64. + # Bash is setup-only; Python and the installed extensions are checked below. + & $bash --version + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + (Split-Path $git) | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + (Split-Path $bash) | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + $sevenZipRoot | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Verify Windows ARM64 runner + if: ${{ inputs.host-platform == 'win-arm64' }} + shell: cmd + run: | + if /I not "%PROCESSOR_ARCHITECTURE%"=="ARM64" ( + echo Expected an ARM64 runner, got %PROCESSOR_ARCHITECTURE%. + exit /b 1 + ) + nvidia-smi || exit /b 1 + - name: Checkout ${{ github.event.repository.name }} uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup proxy cache uses: nv-gha-runners/setup-proxy-cache@main continue-on-error: true + if: ${{ inputs.host-platform == 'win-64' }} with: enable-apt: true - name: Install GPU driver - if: ${{ matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }} + if: ${{ inputs.host-platform == 'win-64' && matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }} env: DRIVER: ${{ matrix.DRIVER }} GPU_TYPE: ${{ matrix.GPU }} @@ -126,6 +229,7 @@ jobs: ci/tools/install_gpu_driver.ps1 - name: Configure driver mode + if: ${{ inputs.host-platform == 'win-64' }} env: DRIVER_MODE: ${{ matrix.DRIVER_MODE }} run: | @@ -135,6 +239,9 @@ jobs: run: | nvidia-smi + - name: Verify driver mode + if: ${{ inputs.host-platform == 'win-64' }} + run: | $mode_output = nvidia-smi | Select-String -Pattern "${{ matrix.DRIVER_MODE }}" Write-Output "Driver mode check: $mode_output" if ("$mode_output" -eq "") { @@ -289,12 +396,29 @@ jobs: Get-ChildItem -Recurse -Force $env:CUDA_CORE_TEST_BINARIES_DIR | Select-Object Mode, LastWriteTime, Length, FullName - name: Set up Python ${{ matrix.PY_VER }} + if: ${{ inputs.host-platform != 'win-arm64' }} uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.PY_VER }} + architecture: x64 # TODO: remove allow-prereleases once 3.15 is officially supported allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }} + - name: Set up Python ${{ matrix.PY_VER }} for Windows ARM64 + if: ${{ inputs.host-platform == 'win-arm64' }} + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: ${{ matrix.PY_VER }} + architecture: arm64 + # TODO: remove allow-prereleases once 3.15 is officially supported + allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }} + + - name: Verify Python architecture + if: ${{ inputs.host-platform == 'win-arm64' }} + run: | + python -VV + python -c "import platform, struct, sysconfig; machine = platform.machine().lower(); target = sysconfig.get_platform(); bits = 8 * struct.calcsize('P'); print(f'machine={machine}, platform={target}, bits={bits}'); assert machine in {'arm64', 'aarch64'}; assert target == 'win-arm64'; assert bits == 64" + - name: Enable Scientific Python Nightly Wheels for Python 3.15 if: ${{ (inputs.test-bindings || inputs.test-core || inputs.test-python) && startsWith(matrix.PY_VER, '3.15') }} @@ -304,6 +428,7 @@ jobs: echo "PIP_ONLY_BINARY=numpy" >> "$GITHUB_ENV" - name: Verify LongPathsEnabled + if: ${{ inputs.host-platform == 'win-64' }} run: | $val = (Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled').LongPathsEnabled echo "LongPathsEnabled = $val" @@ -319,6 +444,7 @@ jobs: with: host-platform: ${{ inputs.host-platform }} cuda-version: ${{ matrix.CUDA_VER }} + cuda-channel: ${{ (matrix.CUDA_VER == inputs.build-ctk-ver && inputs.build-ctk-channel) || 'stable' }} - name: Set up test repetition on nightly runs shell: bash --noprofile --norc -xeuo pipefail {0} @@ -342,14 +468,35 @@ jobs: shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests bindings + - name: Run cuda.bindings tests with per-thread default stream + if: ${{ inputs.test-mode == 'standard' && inputs.test-bindings && inputs.test-bindings-ptds && env.SKIP_CUDA_BINDINGS_TEST == '0' }} + env: + CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM: '1' + CUDA_VER: ${{ matrix.CUDA_VER }} + LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + SKIP_CYTHON_TEST: '1' + shell: bash --noprofile --norc -xeuo pipefail {0} + run: run-tests bindings + + - name: Verify native cuda.bindings extension + if: ${{ inputs.test-mode == 'standard' && inputs.host-platform == 'win-arm64' && inputs.test-bindings }} + run: | + python -c "import sysconfig; import cuda.bindings.driver as driver; suffix = sysconfig.get_config_var('EXT_SUFFIX'); print(driver.__file__); assert suffix and driver.__file__.endswith(suffix); assert sysconfig.get_platform() == 'win-arm64'" + - name: Run cuda.core tests if: ${{ inputs.test-mode == 'standard' && inputs.test-core }} env: CUDA_VER: ${{ matrix.CUDA_VER }} LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + USE_LOCAL_CTK_TEST_DEPS: ${{ (inputs.host-platform == 'win-arm64' && matrix.LOCAL_CTK == '1' && '1') || '0' }} shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests core + - name: Verify native cuda.core import + if: ${{ inputs.test-mode == 'standard' && inputs.host-platform == 'win-arm64' && inputs.test-core }} + run: | + python -c "import sysconfig; import cuda.core; print(cuda.core.__file__); assert sysconfig.get_platform() == 'win-arm64'" + - name: Ensure cuda-python installable if: ${{ inputs.test-mode == 'standard' && inputs.test-python && env.BINDINGS_SOURCE == 'main' }} run: | @@ -371,8 +518,12 @@ jobs: } pip install --only-binary=:all: @dependencyArgs @pythonRequirements + # The WoA prerelease uses the local mini CTK because the full public CUDA + # component wheel set is not available; its pathfinder run above still + # exercises every discoverable component in see_what_works mode. - name: Install cuda.pathfinder extra wheels for testing - if: ${{ inputs.test-mode == 'standard' && inputs.test-pathfinder }} + if: ${{ inputs.test-mode == 'standard' && inputs.test-pathfinder && + (inputs.host-platform != 'win-arm64' || matrix.LOCAL_CTK != '1') }} shell: bash --noprofile --norc -xeuo pipefail {0} run: | pushd cuda_pathfinder @@ -381,7 +532,8 @@ jobs: popd - name: Run cuda.pathfinder tests with all_must_work - if: ${{ inputs.test-mode == 'standard' && inputs.test-pathfinder }} + if: ${{ inputs.test-mode == 'standard' && inputs.test-pathfinder && + (inputs.host-platform != 'win-arm64' || matrix.LOCAL_CTK != '1') }} env: CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work CUDA_PATHFINDER_TEST_FIND_NVIDIA_HEADERS_STRICTNESS: all_must_work diff --git a/ci/test-matrix.yml b/ci/test-matrix.yml index 8e859af1576..0f6f762852b 100644 --- a/ci/test-matrix.yml +++ b/ci/test-matrix.yml @@ -10,7 +10,8 @@ # # [ARCH, PY_VER, CUDA_VER, LOCAL_CTK, GPU, GPU_COUNT, DRIVER] # -# Windows entries also include DRIVER_MODE. +# Windows x64 entries also include DRIVER_MODE. RUNNER optionally overrides the +# generated self-hosted runner label for platforms with dedicated hardware. # # Notes: # - DRIVER accepts: @@ -134,6 +135,8 @@ windows: # special runners - { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.3.0', LOCAL_CTK: '1', GPU: 't4', GPU_COUNT: '2', DRIVER: 'latest', DRIVER_MODE: 'TCC' } - { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.3.0', LOCAL_CTK: '0', GPU: 'h100', GPU_COUNT: '2', DRIVER: 'latest', DRIVER_MODE: 'MCDM' } + # win-arm64 + - { ARCH: 'arm64', PY_VER: '3.13', CUDA_VER: '13.4.0', LOCAL_CTK: '1', GPU: 'gb10', GPU_COUNT: '1', DRIVER: 'latest', RUNNER: 'windows-arm64-1xgb10' } nightly: # nightly-pytorch - { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu126' } } diff --git a/ci/tools/run-tests b/ci/tools/run-tests index f9cc5a9e870..6bf9f43b274 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -99,9 +99,15 @@ elif [[ "${test_module}" == "core" || "${test_module}" == nightly-* ]]; then echo "Installing bindings (source: ${BINDINGS_SOURCE})" pip install "${BINDINGS_ARGS[@]}" echo "Installing core wheel" - # Constrain cuda-toolkit to the requested CTK version to avoid - # pip pulling in a newer nvidia-cuda-runtime that conflicts with it. - pip install "${CORE_WHL[@]}" --group "test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}" "cuda-toolkit==${TEST_CUDA_MAJOR_MINOR}.*" + if [[ "${USE_LOCAL_CTK_TEST_DEPS:-0}" == 1 ]]; then + # Windows ARM64 prerelease packages are tested against the extracted + # local toolkit; public CUDA component and CuPy wheels are not available. + pip install "${CORE_WHL[@]}" --group "test" + else + # Constrain cuda-toolkit to the requested CTK version to avoid + # pip pulling in a newer nvidia-cuda-runtime that conflicts with it. + pip install "${CORE_WHL[@]}" --group "test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}" "cuda-toolkit==${TEST_CUDA_MAJOR_MINOR}.*" + fi echo "Installed packages before core tests:" pip list echo "Running core tests"