Skip to content
Draft
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
7 changes: 0 additions & 7 deletions .github/workflows/executorch-build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,6 @@ jobs:
python -m pip install pyyaml "executorch==1.4.1"
export TORCH_TENSORRT_EXECUTORCH_RUNTIME_VERSION="$(python -c 'import importlib.metadata; print(importlib.metadata.version("torch-tensorrt"))')"

# The downloaded wheel has to carry the C++ runtime. A wheel built with
# PYTHON_ONLY=1 has no libtorchtrt.so, which leaves
# ENABLED_FEATURES.torch_tensorrt_runtime False, and the export near the
# end of this script then fails after the Bazel builds have already run.
# Check it here so the wrong wheel is reported as the wrong wheel.
python -c 'from torch_tensorrt._features import ENABLED_FEATURES as f; assert f.torch_tensorrt_runtime, f'

# Bazel truncates a failing action's output at 1 MB by default and then
# prints nothing but the size, which hid the real error behind
# stdout ... exceeds maximum size of
Expand Down
7 changes: 6 additions & 1 deletion py/torch-tensorrt-executorch-runtime/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,12 @@ def build_extension(self, ext: Extension) -> None:
source = built.parent / dependency
if not source.is_file():
raise RuntimeError(f"Bazel did not produce {source}")
shutil.copy2(source, output.parent / dependency)
destination = output.parent / dependency
# ``build_extension`` runs once for each extension. The first copy
# preserves Bazel's read-only mode, so remove it before the second
# extension tries to copy the same dependency.
destination.unlink(missing_ok=True)
shutil.copy2(source, destination)


require_cuda_13()
Expand Down
5 changes: 0 additions & 5 deletions py/torch_tensorrt/_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1396,11 +1396,6 @@ def _write_external_tensor_data(executorch_program: Any, file_path: str) -> None

def _save_as_executorch(exp_program: Any, file_path: str, **kwargs: Any) -> None:
"""Save an engine-bearing ExportedProgram as an ExecuTorch program."""
if not ENABLED_FEATURES.torch_tensorrt_runtime:
raise RuntimeError(
"output_format='executorch' requires the Torch-TensorRT runtime "
"(torch_tensorrt_runtime). Reinstall torch_tensorrt with the runtime extension."
)
try:
from torch_tensorrt.executorch import export
except ImportError:
Expand Down
14 changes: 13 additions & 1 deletion py/torch_tensorrt/dynamo/runtime/_TRTEngine.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _current_serialized_platform() -> str:
"""Return the current platform using the engine-metadata representation."""
platform = Platform.current_platform()
return (
platform._to_serialized_rt_platform()
cast(str, platform._to_serialized_rt_platform())
if ENABLED_FEATURES.torch_tensorrt_runtime
else str(platform)
)
Expand Down Expand Up @@ -368,6 +368,18 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return self.__str__()

def serialize_metadata_only(self) -> List[Any]:
"""Return the serialized layout without base64-encoding the engine bytes.

This mirrors the C++ runtime accessor used by ExecuTorch export when it
only needs engine metadata. The record keeps its normal shape, but the
engine slot is deliberately empty; callers that need the engine must
use ``__getstate__`` instead.
"""
serialized_info = list(self.serialized_info)
serialized_info[ENGINE_IDX] = ""
return serialized_info

def __getstate__(self) -> Tuple[List[Any], str]:
"""Return pickle state in the same shape as C++ ``ScriptObject.__getstate__``.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any, Dict, List

import torch
from torch_tensorrt._features import ENABLED_FEATURES
from torch_tensorrt.dynamo.runtime._TorchTensorRTModule import TorchTensorRTModule

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -225,7 +226,6 @@ def fake_tensorrt_execute_engine(
)


@torch._library.register_fake_class("tensorrt::Engine")
class FakeTRTEngine:
def __init__(self, engine_info: List[str]) -> None:
self.version = engine_info[torch.ops.tensorrt.ABI_TARGET_IDX()]
Expand Down Expand Up @@ -304,6 +304,12 @@ def __getstate__(self) -> Any:
pass


if ENABLED_FEATURES.torch_tensorrt_runtime:
# Registration is a side effect; retaining the decorator's return value is
# unnecessary and mypy correctly rejects rebinding a class name here.
torch._library.register_fake_class("tensorrt::Engine")(FakeTRTEngine)


@torch.library.custom_op( # type: ignore[misc]
"tensorrt::no_op_placeholder_for_execute_engine", mutates_args=()
)
Expand Down
9 changes: 1 addition & 8 deletions py/torch_tensorrt/executorch/_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ def _apply_weight_streaming_budget(
"""
from executorch.exir.backend.compile_spec_schema import CompileSpec
from torch_tensorrt.executorch.partitioner import (
normalize_weight_streaming_budget_per_engine,
WEIGHT_STREAMING_BUDGET_COMPILE_SPEC_KEY,
normalize_weight_streaming_budget_per_engine,
)

for name, specs in method_compile_specs.items():
Expand Down Expand Up @@ -438,18 +438,11 @@ def export(
executorch.exir.EdgeProgramManager: The Edge program, ready for inspection,
further transformation, or ``to_executorch()``.
"""
from torch_tensorrt._features import ENABLED_FEATURES

if platform.system() != "Linux":
raise ValueError(
f"The executorch format is only supported on Linux, {platform.system()} "
"is not a supported platform for this format"
)
if not ENABLED_FEATURES.torch_tensorrt_runtime:
raise RuntimeError(
"ExecuTorch export requires the Torch-TensorRT runtime "
"(torch_tensorrt_runtime). Reinstall torch_tensorrt with the runtime extension."
)
if inputs is not None and arg_inputs is not None:
raise ValueError("inputs and arg_inputs are mutually exclusive.")
arguments = inputs if inputs is not None else arg_inputs
Expand Down
14 changes: 8 additions & 6 deletions py/torch_tensorrt/executorch/_export_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,24 @@ def _seed_graph_bound_leaves(value: Any, memo: dict[int, Any]) -> None:


def _warn_missing_accessor(name: str) -> None:
"""Warn once per accessor that the loaded runtime predates it.
"""Warn once per accessor that the engine's native runtime predates it.

Without this the only symptom is that export gets slower: the fallback is
correct, it just re-serializes the whole ICudaEngine and base64-encodes it.
It means the Torch-TensorRT C++ library is older than this Python package,
i.e. a source or editable build where only the Python half was rebuilt; a
wheel ships both halves together, so an unmodified wheel should not see it.
The engine may have come from a Torch-TensorRT C++ library older than this
Python package. That can be a mismatched source/editable build, or, for a
Python-only wheel, an engine loaded from an external or previously-built
native runtime.
"""
if name in _WARNED_MISSING:
return
_WARNED_MISSING.add(name)
logger.warning(
"TensorRT runtime has no %s(); falling back to full engine serialization "
"on every read of this engine's info. This is correct but slower, and "
"means the Torch-TensorRT C++ library loaded from torch_tensorrt/lib "
"predates this Python package -- rebuild the C++ side to avoid it.",
"means this engine was created by a Torch-TensorRT C++ runtime that "
"predates this Python package. Rebuild or reinstall the matching native "
"runtime (or regenerate the engine) to avoid it.",
name,
)

Expand Down
13 changes: 11 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,16 @@ def run(self):

package_data = {}

# ExecuTorch export uses the Python fake/meta kernels to represent TensorRT
# engine calls while lowering. They do not depend on the native Torch-TensorRT
# runtime, so Python-only wheels must ship them too.
packages += ["torch_tensorrt.dynamo.runtime.meta_ops"]
package_dir.update(
{
"torch_tensorrt.dynamo.runtime.meta_ops": "py/torch_tensorrt/dynamo/runtime/meta_ops",
}
)

if not (PY_ONLY or NO_TS):
tensorrt_x86_64_external_dir = (
lambda: subprocess.check_output(
Expand Down Expand Up @@ -918,12 +928,11 @@ def run(self):
)
]

packages += ["torch_tensorrt.ts", "torch_tensorrt.dynamo.runtime.meta_ops"]
packages += ["torch_tensorrt.ts"]

package_dir.update(
{
"torch_tensorrt.ts": "py/torch_tensorrt/ts",
"torch_tensorrt.dynamo.runtime.meta_ops": "py/torch_tensorrt/dynamo/runtime/meta_ops",
}
)

Expand Down
Loading