diff --git a/.ci/docker/common/install_cuda_windows_cross_compile.sh b/.ci/docker/common/install_cuda_windows_cross_compile.sh index b5d92c8215d..a2fc4cc278f 100644 --- a/.ci/docker/common/install_cuda_windows_cross_compile.sh +++ b/.ci/docker/common/install_cuda_windows_cross_compile.sh @@ -14,7 +14,6 @@ INSTALL_DIR="${WINDOWS_CUDA_INSTALL_DIR:-/opt/cuda-windows}" # Mapping of CUDA versions to their corresponding driver versions for Windows installers # Source: https://developer.nvidia.com/cuda-toolkit-archive declare -A CUDA_DRIVER_MAP=( - ["12.6"]="12.6.3:561.17" ["12.8"]="12.8.1:572.61" ["12.9"]="12.9.1:576.57" ["13.0"]="13.0.2:" diff --git a/.ci/scripts/cuda_benchmark.py b/.ci/scripts/cuda_benchmark.py index 1fc984ee484..c32b5c86f5b 100644 --- a/.ci/scripts/cuda_benchmark.py +++ b/.ci/scripts/cuda_benchmark.py @@ -588,7 +588,7 @@ def to_v3_format( workflow_run_id: GitHub workflow run ID workflow_run_url: GitHub workflow run URL gpu_name: GPU device name (e.g., "Tesla V100", "A100") - cuda_driver_version: CUDA driver version (e.g., "12.6", "535.104.05") + cuda_driver_version: CUDA driver version (e.g., "13.0", "535.104.05") Returns: List of benchmark records in v3 format @@ -873,7 +873,7 @@ def main(): "--cuda_driver_version", type=str, default=None, - help="CUDA driver version (e.g., '12.6', '535.104.05') - optional for v3 format", + help="CUDA driver version (e.g., '13.0', '535.104.05') - optional for v3 format", ) parser.add_argument("--verbose", action="store_true", help="Print verbose output") diff --git a/.ci/scripts/tests/test_cu134_dependencies.py b/.ci/scripts/tests/test_cu134_dependencies.py index a8af05f11d7..2812a34d5df 100644 --- a/.ci/scripts/tests/test_cu134_dependencies.py +++ b/.ci/scripts/tests/test_cu134_dependencies.py @@ -103,7 +103,7 @@ def test_all_install_steps_preserve_exact_cu134_selection(self): ) def test_other_cuda_trains_keep_existing_pins(self): - for cuda in ((12, 6), (13, 0), (13, 2)): + for cuda in ((13, 0), (13, 2)): for machine in ("x86_64", "aarch64"): with self.subTest(cuda=cuda, machine=machine): core, local, domains, examples = self.install_commands( @@ -159,7 +159,7 @@ def test_cpu_release_dependencies_are_opt_in(self): ) def test_cpu_release_option_keeps_cuda_pins(self): - for cuda in ((12, 6), (13, 0), (13, 2), (13, 4)): + for cuda in ((13, 0), (13, 2), (13, 4)): for machine in ("x86_64", "aarch64"): with self.subTest(cuda=cuda, machine=machine): self.assertEqual( diff --git a/.ci/scripts/tests/test_cuda_workflow.py b/.ci/scripts/tests/test_cuda_workflow.py index 112f9a6f5e1..cb0d904229f 100644 --- a/.ci/scripts/tests/test_cuda_workflow.py +++ b/.ci/scripts/tests/test_cuda_workflow.py @@ -34,9 +34,7 @@ def _model_quant(entry): class CudaWorkflowTest(unittest.TestCase): def test_build_matrix_preserves_existing_cuda_versions(self): job = WORKFLOW["jobs"]["test-cuda-builds"] - self.assertEqual( - job["strategy"]["matrix"]["cuda-version"], ["12.6", "13.0", "13.4"] - ) + self.assertEqual(job["strategy"]["matrix"]["cuda-version"], ["13.0", "13.4"]) self.assertEqual(job["with"]["gpu-arch-version"], "${{ matrix.cuda-version }}") def test_cuda_builds_take_the_node_driver_on_an_unpinned_v3(self): @@ -58,9 +56,7 @@ def test_cuda_runtime_update_precedes_build_and_propagates_failure(self): source() { printf 'BUILD %s\n' "$*"; printf 'LIBRARY PATH %s\n' "$LD_LIBRARY_PATH"; } """ for version, conda_status in ( - (version, status) - for version in ("12.6", "13.0", "13.4") - for status in (0, 1) + (version, status) for version in ("13.0", "13.4") for status in (0, 1) ): with self.subTest(version=version, conda_status=conda_status): result = subprocess.run( diff --git a/.ci/scripts/wheel/cuda_arch_list.sh b/.ci/scripts/wheel/cuda_arch_list.sh index 9e74af6c644..6c9e461291a 100644 --- a/.ci/scripts/wheel/cuda_arch_list.sh +++ b/.ci/scripts/wheel/cuda_arch_list.sh @@ -41,29 +41,6 @@ _cuda_arch_aarch64_cu130="8.0 9.0 10.0 11.0 12.0" _cuda_arch_aarch64_cu132="${_cuda_arch_aarch64_cu130}" _cuda_arch_aarch64_cu134="${_cuda_arch_aarch64_cu130}" -# The older CUDA train. -# -# The two architectures do not carry identical lists, because each covers what the published PyTorch -# build for that architecture covers, and those differ. Matching them to each other instead would mean -# advertising a GPU on one architecture that PyTorch cannot serve there. -# -# The smaller embedded modules are deliberately absent, with one exception. An embedded-only -# architecture in a generic wheel would advertise a device the row cannot otherwise serve, since -# those devices also need the CUDA, TensorRT and PyTorch pinned by their own software release -# rather than the ones a generic wheel resolves. -# -# 8.7 is that exception. This is the only row whose CUDA major matches what that module's software -# release ships, and the wheel declares no PyTorch, so the user supplies the build that carries -# their architecture. Omitting it does not protect them from a bad pairing, it only removes the -# device code they need. -# -# The floor is 8.0 rather than the oldest architecture PyTorch still carries. One of these sources compiles -# an integer matrix-multiply path only at 8.0 and newer, so an older architecture would get a delegate that -# loads, runs most models, and fails on one that needs that operator. Claiming hardware the delegate only -# partly serves is the same problem the embedded modules have, so the row leaves it out for the same reason. -_cuda_arch_x86_64_cu126="8.0 8.6 8.9 9.0" -_cuda_arch_aarch64_cu126="8.0 8.7 9.0" - # A CUDA train with no architecture list would leave the build detecting the builder's GPU, which is # the failure this file exists to prevent. Adding a train to the release matrix without adding its # architectures should fail loudly rather than silently produce a single-GPU wheel. @@ -103,7 +80,6 @@ executorch_cuda_arch_list() { case "${machine}" in aarch64 | arm64) case "${train}" in - 126) printf '%s' "${_cuda_arch_aarch64_cu126}" ;; 130) printf '%s' "${_cuda_arch_aarch64_cu130}" ;; 132) printf '%s' "${_cuda_arch_aarch64_cu132}" ;; 134) printf '%s' "${_cuda_arch_aarch64_cu134}" ;; @@ -112,7 +88,6 @@ executorch_cuda_arch_list() { ;; x86_64) case "${train}" in - 126) printf '%s' "${_cuda_arch_x86_64_cu126}" ;; 130) printf '%s' "${_cuda_arch_x86_64_cu130}" ;; 132) printf '%s' "${_cuda_arch_x86_64_cu132}" ;; 134) printf '%s' "${_cuda_arch_x86_64_cu134}" ;; diff --git a/.ci/scripts/wheel/test_shared_libraries.py b/.ci/scripts/wheel/test_shared_libraries.py index bf39abf294a..ed7134a2766 100644 --- a/.ci/scripts/wheel/test_shared_libraries.py +++ b/.ci/scripts/wheel/test_shared_libraries.py @@ -1217,7 +1217,7 @@ def _wheel_cuda_train() -> str: """The CUDA train the installed wheel was built for, or "" for a CPU wheel. Read from the local version segment, which is the only place the wheel states what - it was built for. `1.5.0+cu126` gives "126". + it was built for. `1.5.0+cu132` gives "132". """ local = importlib.metadata.version("executorch").partition("+")[2] return local[2:] if local.startswith("cu") else "" @@ -1360,7 +1360,7 @@ def _resolve_required(required): ), # The CUDA components. Required exactly when the wheel says it is a CUDA wheel, # which is decided at check time rather than here: a fixed False meant a wheel - # tagged +cu126 carrying no CUDA library at all passed every check in this file, + # tagged +cu132 carrying no CUDA library at all passed every check in this file, # while a fixed True would fail every CPU wheel. The marker is the string these # rows are keyed on below. ( @@ -1457,7 +1457,7 @@ def test_each_component_has_one_owner() -> None: shipped = {path.name for path in _shipped_shared_objects(_installed_package_dir())} for what, symbols, owner, required in _OWNED_COMPONENTS: # Resolved here rather than in the table, because it depends on the installed - # wheel. A fixed False let a wheel tagged +cu126 ship with no CUDA library at + # wheel. A fixed False let a wheel tagged +cu132 ship with no CUDA library at # all and still pass, which is the whole point of the conditional rows. required = _resolve_required(required) present = any(name.startswith(owner) for name in shipped) diff --git a/.github/scripts/filter_cuda_matrix.py b/.github/scripts/filter_cuda_matrix.py index 66b2130f1a5..568345bb256 100644 --- a/.github/scripts/filter_cuda_matrix.py +++ b/.github/scripts/filter_cuda_matrix.py @@ -53,12 +53,6 @@ # Skip wholly absent trains so an upstream removal cannot block the remaining releases. # Offered trains must still cover every supported Python version. # -# cu126 was the floor until PyTorch stopped offering it on the nightly channel. The generator -# still offers it when a release is cut, so keeping it here would publish a train that no -# nightly has built since, and a release is the wrong place to find out that it no longer -# builds. A machine on CUDA 12.6 can still build from source, where the pinned torch comes -# from a channel that carries 12.6. -# # cu130 is not published. PyTorch keeps it on its nightly builds only as a temporary hold for # other projects, and its release-candidate builds do not carry it, so a release would have # no cu130 train even while nightlies do. @@ -91,9 +85,8 @@ # version. Kept empty on purpose today, so no Jetson row is emitted. # # Published PyTorch stopped shipping sm_87 device code after 2.8.0, so a Jetson row today -# would produce a wheel whose PyTorch dependency cannot execute on the device. The aarch64 -# CUDA 12.6 row, which was the one that compiled sm_87 device code for an embedded module, -# is no longer published either. Populate this when both change. +# would produce a wheel whose PyTorch dependency cannot execute on the device, and no +# published row compiles sm_87 device code. Populate this when both change. # # Because both lists are empty, asking for the JetPack rows can only produce an empty result. # No workflow asks, and the request is rejected up front with that reason rather than left to diff --git a/.github/workflows/cuda.yml b/.github/workflows/cuda.yml index f87fed8ebd6..56bf2f71262 100644 --- a/.github/workflows/cuda.yml +++ b/.github/workflows/cuda.yml @@ -1,6 +1,6 @@ # Test ExecuTorch CUDA Build Compatibility # This workflow tests whether ExecuTorch can be successfully built with CUDA support -# across different CUDA versions (12.6, 13.0, 13.4) using the command: +# across different CUDA versions (13.0, 13.4) using the command: # ./install_executorch.sh # # It also runs model accuracy (e2e EXPECTED_OUTPUT checks) and, for the perf @@ -142,7 +142,7 @@ jobs: strategy: fail-fast: false matrix: - cuda-version: ["12.6", "13.0", "13.4"] + cuda-version: ["13.0", "13.4"] name: test-executorch-cuda-build-${{ matrix.cuda-version }} uses: pytorch/test-infra/.github/workflows/linux_job_v3.yml@main @@ -159,8 +159,8 @@ jobs: script: | set -eux - # AOTI model libraries need a newer C++ runtime than the 12.6 image's - # system library; the 13.4 image also needs the thread-local cleanup fix. + # AOTI model libraries need a newer C++ runtime than the image's system + # library; the 13.4 image also needs the thread-local cleanup fix. conda install -y -n base -c conda-forge 'libstdcxx-ng=16.2.0' 'libgcc-ng=16.2.0' export LD_LIBRARY_PATH="/opt/conda/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" source .ci/scripts/test-cuda-build.sh "${{ matrix.cuda-version }}" diff --git a/.github/workflows/vulkan.yml b/.github/workflows/vulkan.yml index c5444844a34..ec81451f6cd 100644 --- a/.github/workflows/vulkan.yml +++ b/.github/workflows/vulkan.yml @@ -79,7 +79,7 @@ jobs: timeout: 120 runner: mt-l-x86aavx2-11-41-a10g gpu-arch-type: cuda - gpu-arch-version: "12.6" + gpu-arch-version: "13.2" submodules: recursive ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} script: | @@ -171,7 +171,7 @@ jobs: timeout: 180 runner: mt-l-x86aavx2-11-41-a10g gpu-arch-type: cuda - gpu-arch-version: "12.6" + gpu-arch-version: "13.2" submodules: recursive ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} upload-artifact: vulkan-llm-e2e diff --git a/docs/source/backends/cuda/cuda-overview.md b/docs/source/backends/cuda/cuda-overview.md index fd2a2471a15..e1fdb427f68 100644 --- a/docs/source/backends/cuda/cuda-overview.md +++ b/docs/source/backends/cuda/cuda-overview.md @@ -17,7 +17,7 @@ Below are the requirements for running a CUDA-delegated ExecuTorch model: - **Hardware**: NVIDIA GPU with compute capability 8.0 (Ampere) or newer. This is the floor the prebuilt packages are built for. - **CUDA**: 13 for the prebuilt packages. On Linux they bring the CUDA runtime with them. On - Windows it comes from a CUDA 13 toolkit install. A build from source also supports CUDA 12.6. + Windows it comes from a CUDA 13 toolkit install. A build from source also supports CUDA 13.0. - **Operating System**: Linux, or Windows from C++ for programs exported on Linux (see [CUDA on Windows](../../using-executorch-cpp.md#cuda-on-windows)) - **Drivers**: An NVIDIA driver that supports the CUDA version you use: CUDA 13 for the prebuilt diff --git a/install_utils.py b/install_utils.py index 4e1397413b3..d96ac876fbb 100644 --- a/install_utils.py +++ b/install_utils.py @@ -18,7 +18,6 @@ # Supported CUDA versions - modify this to add/remove supported versions # Format: tuple of (major, minor) version numbers SUPPORTED_CUDA_VERSIONS = ( - (12, 6), (13, 0), (13, 2), (13, 4), @@ -114,7 +113,7 @@ def _get_cuda_version(): _selected_nvcc(), capture_output=True, text=True, check=True ) # Parse nvcc output for CUDA version - # Output contains line like "Cuda compilation tools, release 12.6, V12.6.68" + # Output contains line like "Cuda compilation tools, release 13.0, V13.0.88" match = re.search(r"release (\d+)\.(\d+)", nvcc_result.stdout) if match: major, minor = int(match.group(1)), int(match.group(2)) @@ -301,11 +300,11 @@ def _cuda_version_to_pytorch_suffix(major, minor): Generate PyTorch CUDA wheel suffix from CUDA version numbers. Args: - major: CUDA major version (e.g., 12) - minor: CUDA minor version (e.g., 6) + major: CUDA major version (e.g., 13) + minor: CUDA minor version (e.g., 2) Returns: - PyTorch wheel suffix string (e.g., "cu126") + PyTorch wheel suffix string (e.g., "cu132") """ return f"cu{major}{minor}" diff --git a/setup.py b/setup.py index d5f2c593d00..6df62e34088 100644 --- a/setup.py +++ b/setup.py @@ -735,9 +735,9 @@ def _cuda_train() -> str: Raises when a release row names a train the installed toolkit does not provide. The declared packages and the loader paths both come from this value, so disagreeing with - the toolkit that compiled the libraries produces a wheel that installs cleanly and then - cannot load: a cu126 row built against a 13.0 toolkit declares the CUDA 12 runtime for - binaries that need libcudart.so.13. + the toolkit that compiled the libraries produces a wheel that installs cleanly but + declares a train it was not compiled for, such as a cu134 row built against a 13.2 + toolkit. """ # An explicit OFF first, ahead of the release field. A CPU row on a builder that has a # toolkit installed sets both, so reading the row field first would declare a runtime