Skip to content

Commit f1185c7

Browse files
committed
Make the CUDA docs agree with the TensorRT page
The CUDA backend page and the getting started page said several things that the TensorRT page, and the code, contradict: - The CUDA page said the Python runtime allocates host memory for an unplanned output, so a method that keeps its outputs on the GPU could not run from Python. The Python runtime allocates a new device buffer for each call. - It said a planned input fed with GPU memory makes an undefined host memcpy and crashes. The runtime refuses that copy and the call fails with NotSupported. - It asked for a CUDA 11.x or later toolkit to run a model. The prebuilt packages use CUDA 13 and bring the CUDA runtime with them on Linux, a build from source also supports CUDA 12.6, and the toolkit is needed for export, where nvcc compiles the kernels. It also gave no minimum GPU, while the packages are built for compute capability 8.0 and newer, and it asked for Python 3.8+, while the package needs 3.11 to 3.15. - It listed Windows without saying that programs for Windows are exported on Linux. It now links to the C++ guide section that shows how. Its link to the getting started page was also broken. - The getting started page said to use the CPU packages on Windows, while CUDA packages are built for Windows too, and it called CUDA 13.4 nightly only.
1 parent 4217323 commit f1185c7

2 files changed

Lines changed: 28 additions & 25 deletions

File tree

‎docs/source/backends/cuda/cuda-overview.md‎

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,27 @@ The CUDA backend is the ExecuTorch solution for running models on NVIDIA GPUs. I
77
- **Optimized GPU Execution**: Uses AOTInductor to generate highly optimized CUDA kernels for model operators
88
- **Triton Kernel Support**: Leverages Triton for GEMM (General Matrix Multiply), convolution, and SDPA (Scaled Dot-Product Attention) kernels.
99
- **Quantization Support**: INT4 weight quantization with tile-packed format for improved performance and reduced memory footprint
10-
- **Cross-Platform**: Supports both Linux and Windows platforms
10+
- **Cross-Platform**: Runs on Linux and Windows. Programs for Windows are exported on Linux.
1111
- **Multiple Model Support**: Works with various models including LLMs, vision-language models, and audio models
1212

1313
## Target Requirements
1414

1515
Below are the requirements for running a CUDA-delegated ExecuTorch model:
1616

17-
- **Hardware**: NVIDIA GPU with CUDA compute capability
18-
- **CUDA Toolkit**: CUDA 11.x or later (CUDA 12.x recommended)
19-
- **Operating System**: Linux or Windows
17+
- **Hardware**: NVIDIA GPU with compute capability 8.0 (Ampere) or newer
18+
- **CUDA**: 13 for the prebuilt packages, which bring the CUDA runtime with them on Linux. A build
19+
from source also supports CUDA 12.6.
20+
- **Operating System**: Linux, or Windows for programs exported on Linux (see
21+
[CUDA on Windows](../../using-executorch-cpp.md#cuda-on-windows))
2022
- **Drivers**: PyTorch-Compatible NVIDIA GPU drivers installed
2123

2224
## Development Requirements
2325

2426
To develop and export models using the CUDA backend:
2527

26-
- **Python**: Python 3.8+
28+
- **Python**: Python 3.11 to 3.15
2729
- **PyTorch**: PyTorch with CUDA support
30+
- **CUDA Toolkit**: export compiles kernels with `nvcc`, the CUDA compiler, so it needs a CUDA toolkit
2831
- **ExecuTorch**: Install ExecuTorch with CUDA backend support
2932

3033
## Using the CUDA Backend
@@ -83,7 +86,7 @@ For a complete working example, see the [CUDA export script](https://github.com/
8386

8487
## Runtime Integration
8588

86-
To run the model on device, use the standard ExecuTorch runtime APIs. See [Running on Device](getting-started.md#running-on-device) for more information.
89+
To run the model on device, use the standard ExecuTorch runtime APIs. See [Running on Device](../../getting-started.md#running-on-device) for more information.
8790

8891
When building from source, pass `-DEXECUTORCH_BUILD_CUDA=ON` when configuring the CMake build to compile the CUDA backend.
8992

@@ -142,8 +145,8 @@ exec_program = et_program.to_executorch(
142145
enable_non_cpu_memory_planning=True,
143146
# Required alongside the skips. Memory planning reserves a buffer for graph inputs by
144147
# default, and the runtime fills a planned input by copying the caller's memory into that
145-
# buffer, which reintroduces the copy you just asked to skip. On device memory that copy is
146-
# a host memcpy into a device pointer, which is undefined.
148+
# buffer, which reintroduces the copy you just asked to skip. For a device tensor the
149+
# runtime refuses that copy, so the call fails.
147150
# Outputs stay planned, so the runtime allocates them on the device and hands back a
148151
# pointer to its own buffer. See the note below for when to unplan them instead.
149152
memory_planning_pass=MemoryPlanningPass(alloc_graph_input=False),
@@ -171,23 +174,22 @@ during device-aware memory planning.
171174

172175
**Inputs must be unplanned**, via `MemoryPlanningPass(alloc_graph_input=False)`. Without it the
173176
program reserves its own input buffer and the runtime copies the caller's memory into it, so the
174-
copy comes back at run time. On device memory that copy is a host memcpy into a device pointer,
175-
which is undefined, so the program crashes rather than returning a wrong answer.
177+
copy comes back at run time. For a device tensor the runtime refuses that copy, so the call fails
178+
with error `0x10` (`NotSupported`) and the log says `Error copying tensor data at input 0`.
176179

177-
**Outputs have two valid shapes, and which one you want depends on the language.**
180+
**Outputs have two valid shapes.**
178181

179-
Leave outputs planned, which is the default, when the caller cannot supply device memory itself.
180-
The planned buffer is allocated on the device because `enable_non_cpu_memory_planning` is on, and
181-
`skip_d2h_for_method_outputs` means nothing copies it back, so the result stays on the device and
182-
the caller receives a pointer to the runtime's own buffer. That buffer belongs to the method and is
183-
reused by the next execution, so read or copy the result before running again. This is the shape
184-
every Python caller wants, and it is what the exporters in this repository use, for example
182+
Leave outputs planned, which is the default, in most cases. The planned buffer is allocated on the
183+
device because `enable_non_cpu_memory_planning` is on, and `skip_d2h_for_method_outputs` means
184+
nothing copies it back, so the result stays on the device. That buffer belongs to the method and is
185+
reused by the next execution. A C++ caller gets a pointer to it, so read or copy the result before
186+
running again. From Python, `execute()` returns a copy on the GPU unless you pass
187+
`clone_outputs=False`. This is what the exporters in this repository use, for example
185188
`examples/models/gemma4_31b/export.py`.
186189

187-
Set `alloc_graph_output=False` only when the caller supplies the output memory itself, which today
188-
means a C++ caller handing the runtime a device tensor through `Module::set_output`. The Python
189-
bindings allocate host memory for an unplanned output, so a device resident method exported this
190-
way cannot run from Python.
190+
Set `alloc_graph_output=False` when the caller should own the output memory instead. A C++ caller
191+
hands the runtime a device tensor through `Module::set_output`. The Python runtime allocates a new
192+
device buffer for each call and returns it without a copy.
191193

192194
**Per-method selection is on the outer config, not on the flags.** Pass a dict of
193195
`PropagateDeviceConfig` keyed by method name:

‎docs/source/getting-started.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ pip install executorch torch \
3737
| NVIDIA GPU, CUDA 13.2 | `cu132` |
3838
| NVIDIA GPU, CUDA 13.4 | `cu134` |
3939

40-
The CUDA packages are built for Linux, on x86_64 and ARM64. Use the `cpu`
41-
variant on macOS and on Windows. If your CUDA version is not in the table,
40+
The CUDA packages are built for Linux, on x86_64 and ARM64, and for Windows on
41+
x86_64. On Windows they run CUDA programs, but programs for the CUDA backend are
42+
exported on Linux (see [CUDA on Windows](using-executorch-cpp.md#cuda-on-windows)).
43+
Use the `cpu` variant on macOS. If your CUDA version is not in the table,
4244
choose the closest lower one with the same major version, because CUDA works
4345
across minor versions but not across major ones. There is no package for CUDA 12,
4446
so on CUDA 12 use the `cpu` variant or build from source. On CUDA 13.0 or 13.1 no
@@ -54,8 +56,7 @@ To get a change that has landed on the `main` branch but is not in a release
5456
yet, use a nightly build. These are rebuilt every day. Put `nightly/` in front
5557
of the variant name, for example `nightly/cu132`, and add `--pre` to the
5658
command, otherwise pip skips development versions. Nightly builds cover the same
57-
variants. CUDA 13.4 is the newest, and until the next release it is in nightly
58-
builds only.
59+
variants.
5960

6061
The second index is needed because a bare `--index-url` replaces PyPI instead of
6162
adding to it, and some dependencies are published only on PyPI.

0 commit comments

Comments
 (0)