Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion cpp/src/torch_tensorrt/executorch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,24 @@ elseif(_executorch_backend_tensorrt_source_root AND
# than a copy of it, so this stays correct if ExecuTorch changes the target
# and so a duplicate definition is a hard error instead of two libraries.
if(NOT _common_include_directories)
set(_common_include_directories "${_executorch_include_parent}")
set(_common_include_directories
"${_executorch_include_parent}"
"${_executorch_backend_tensorrt_source_root}/runtime/core/portable_type/c10"
)
endif()
# extension_cuda links executorch_core. Built standalone, no ExecuTorch build in this project
# defines it, so stand in the prebuilt core that the delegate links below.
if(NOT TARGET executorch_core)
if(NOT DEFINED EXECUTORCH_CORE_LIBRARY)
set(EXECUTORCH_CORE_LIBRARY
"${_executorch_backend_tensorrt_source_root}/cmake-out/libexecutorch_core.a"
CACHE FILEPATH "Path to the ExecuTorch core static library")
endif()
if(NOT EXISTS "${EXECUTORCH_CORE_LIBRARY}")
message(FATAL_ERROR "EXECUTORCH_CORE_LIBRARY='${EXECUTORCH_CORE_LIBRARY}' does not exist")
endif()
add_library(executorch_core STATIC IMPORTED)
set_target_properties(executorch_core PROPERTIES IMPORTED_LOCATION "${EXECUTORCH_CORE_LIBRARY}")
endif()
add_subdirectory(
"${_executorch_backend_tensorrt_source_root}/extension/cuda"
Expand Down
1,286 changes: 400 additions & 886 deletions cpp/src/torch_tensorrt/executorch/README.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docsrc/py_api/executorch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ torch_tensorrt.executorch

.. note::

This module requires ExecuTorch and is only supported on Linux.
This module needs the ``executorch`` extra. It runs on Linux and on Windows x86-64. See
:ref:`executorch_deployment`.

Overview
--------
Expand Down
5 changes: 3 additions & 2 deletions docsrc/user_guide/compilation/compilation_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,9 @@ Graph Partitioning
slower depending on the GPU, so measure it. In FP16 the result can round
differently; ``use_fp32_acc=True`` reduces that. Only static shapes are
rewritten, and ``scaled_dot_product_attention`` also needs
``decompose_attention=True``. The setting has no effect under ``torch.compile``
with ``use_distributed_mode_trace``.
``decompose_attention=True``. The setting has no effect under ``torch.compile``,
because on PyTorch 2.15 ``torch.compile`` splits each matrix product into
``expand``, ``reshape`` and ``bmm`` before this rewrite runs.

----

Expand Down
684 changes: 399 additions & 285 deletions docsrc/user_guide/runtime_performance/executorch.rst

Large diffs are not rendered by default.

459 changes: 116 additions & 343 deletions docsrc/user_guide/runtime_performance/saving_models.rst

Large diffs are not rendered by default.

419 changes: 159 additions & 260 deletions examples/executorch_reference_runner/README.md

Large diffs are not rendered by default.

15 changes: 5 additions & 10 deletions examples/executorch_reference_runner/load_model_device_resident.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

The program this loads was exported with ``skip_h2d_for_method_inputs`` and
``skip_d2h_for_method_outputs``, so its boundary carries no copy operators and it
wants a CUDA input. A host input still gives the right answer, but it costs a
staging copy that the export existed to remove, so it defeats the point rather
than breaking the program. Where a host-backed buffer tagged for the device does
fail is in the runtime rather than in this delegate, on a device that reports it
cannot read pageable host memory.
wants a CUDA input. ExecuTorch's Python runtime refuses a host input. From C++,
a host input costs a copy on every call when TensorRT reads it first, and fails
when the CUDA backend does.

That contract is what this script checks. ``export_device_resident.py`` already
asserts the serialized program contains no boundary copy operators; this asserts
Expand Down Expand Up @@ -63,11 +61,8 @@
outputs = forward.execute((x,))
y = outputs[0]

# This catches the export flags not taking, and that is all it catches. It does not prove the buffer is
# device memory: the tag and the pointer can disagree, and measured here they do, because the bindings
# hand back a buffer tagged cuda whose pointer is ordinary host memory. Proving residency needs the
# driver's own view of the pointer, which is more machinery than an example should carry, so the honest
# claim is the narrow one. The numbers below are still checked, and they are correct.
# This catches the export flags not taking. It does not ask the driver whether the pointer is device
# memory, which is more machinery than an example should carry; the numbers below are still checked.
if not y.is_cuda:
raise AssertionError(
f"FATAL: output is tagged {y.device}, not cuda. The usual cause is that "
Expand Down
7 changes: 3 additions & 4 deletions examples/torchtrt_executorch_example/export_coalesced.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example::

pip install -e ".[executorch]" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132
Install Torch-TensorRT with its ``executorch`` extra, as the Installation section of
the ExecuTorch deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation

ExecuTorch's CUDA backend also needs a CUDA toolkit (``nvcc``) at export time,
for the AOTInductor compile.
Expand Down
53 changes: 20 additions & 33 deletions examples/torchtrt_executorch_example/export_device_resident.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,20 @@
already has its data on the GPU those copies are pure overhead, and they are what
``PropagateDeviceConfig`` turns off.

Two settings are needed, not one. Skipping the copy is not enough on its own:
memory planning allocates graph inputs and outputs by default, so the runtime
would still reserve its own buffer and fill it from the caller's memory with a
host memcpy, which is undefined for device memory and puts the copy straight
back. ``alloc_graph_input=False`` and ``alloc_graph_output=False`` are what stop
that, and ``enable_non_cpu_memory_planning`` is required for planning to run over
non-CPU tensors at all.

Those two settings choose one of two valid arrangements, and it is worth knowing
which. With them off, as here, nobody allocates the boundary buffers and the
CALLER supplies their addresses, which is what a C++ consumer does and what
ExecuTorch's own reference runner is built for. The other arrangement leaves
planning on, so the program's own device arena owns them; ExecuTorch's own CUDA
example takes that one, calling ``to_executorch()`` with no planning overrides at
all.

The first arrangement cannot work from Python as things stand, because the
bindings do not supply an address for a non-planned output and there is no way to
give them one. Measured: with ExecuTorch's CUDA backend owning the last partition
a program exported this way fails every time, and the C++ error says why, that the
data pointer cannot be null. It appears to work when the TensorRT delegate owns
the last partition only because that delegate does not check, and the buffer it is
handed is host memory.

So run a program exported this way from C++, and export with planning left on if
Python is the target.
Skipping the copies is not enough on its own. Memory planning allocates the
graph inputs by default, and a program that owns its input buffer cannot take a
GPU tensor: setting one fails with error ``0x10`` (``NotSupported``), and the
log says "Error copying tensor data at input 0". So ``alloc_graph_input=False``
is required. ``enable_non_cpu_memory_planning``, on by default, is what lets
planning place tensors in GPU memory at all.

This script also passes ``alloc_graph_output=False``, so the runtime does not
copy the outputs: a C++ caller sets their memory once with
``Module::set_output``, and from Python the runtime allocates it and does not
overwrite an output the caller still holds. Planned outputs work too, but they
live in the program's own GPU memory, which the next call overwrites, and
Python's ``execute()`` copies them on every call unless it gets
``clone_outputs=False``.

This script asserts on the serialized program rather than trusting the flags:
the exported ``.pte`` must contain neither copy operator, and it must still carry
Expand All @@ -57,10 +45,9 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example::

pip install -e ".[executorch]" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132
Install Torch-TensorRT with its ``executorch`` extra, as the Installation section of
the ExecuTorch deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation

ExecuTorch's CUDA backend also needs a CUDA toolkit (``nvcc``) at export time,
for the AOTInductor compile.
Expand Down Expand Up @@ -141,9 +128,9 @@ def main() -> None:
skip_d2h_for_method_outputs=True,
),
enable_non_cpu_memory_planning=True,
# Without these the runtime allocates its own buffer for the
# input and output it was just told not to copy, and fills the
# input from the caller's memory with a host memcpy.
# The runtime refuses to copy the caller's CUDA tensor into a
# planned input, so the input must not be planned. An unplanned
# output is not copied either.
memory_planning_pass=MemoryPlanningPass(
alloc_graph_input=False, alloc_graph_output=False
),
Expand Down
9 changes: 3 additions & 6 deletions examples/torchtrt_executorch_example/export_dynamic_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example::

pip install -e ".[executorch]" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132

See https://pytorch.org/executorch/stable/getting-started-setup.html for details.
Install Torch-TensorRT with its ``executorch`` extra, as the Installation section of
the ExecuTorch deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation
"""

# %%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example::

pip install -e ".[executorch]" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132
Install Torch-TensorRT with its ``executorch`` extra, as the Installation section of
the ExecuTorch deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation
"""

import argparse
Expand Down
16 changes: 5 additions & 11 deletions examples/torchtrt_executorch_example/export_multi_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,12 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example.
The Gemma-3 definition comes from ``transformers``, which that extra does not
pull in::

pip install --pre -e ".[executorch]" "transformers>=5.4.0" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132
Install Torch-TensorRT with its ``executorch`` extra, as the ExecuTorch
deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation

``--pre`` is required: the ExecuTorch companion package has only prerelease
versions on the nightly index, and without it pip falls back to the last
release, which pins an older torch and fails to resolve.

See https://pytorch.org/executorch/stable/getting-started-setup.html for details.
The Gemma-3 definition comes from ``transformers``, which that extra does not
install, so also install ``transformers>=5.4.0``.
"""

# %%
Expand Down
9 changes: 3 additions & 6 deletions examples/torchtrt_executorch_example/export_static_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@

Prerequisites
-------------
Install Torch-TensorRT with the ExecuTorch extra before running this example::

pip install -e ".[executorch]" \
--extra-index-url https://download.pytorch.org/whl/nightly/cu132

See https://pytorch.org/executorch/stable/getting-started-setup.html for details.
Install Torch-TensorRT with its ``executorch`` extra, as the Installation section of
the ExecuTorch deployment guide shows:
https://docs.pytorch.org/TensorRT/user_guide/runtime_performance/executorch.html#installation
"""

# %%
Expand Down
Loading
Loading