Skip to main content

trt-torch-quickstart

Compile a PyTorch model to a TensorRT engine via Torch-TensorRT — AOT or JIT — under the new strong-typing default. Use when the user compiles PyTorch to TensorRT without ONNX, hits "enabled_precisions should not be used when use_explicit_typing=True", sees Dynamo graph breaks or PyTorch fallback, debugs ABI errors at import torch_tensorrt, or needs the compatible torch / torch_tensorrt / tensorrt-cu13 version pins for TensorRT 11. Triggers: torch_tensorrt, torch_tensorrt.dynamo.compile, torch.compile backend torch_tensorrt, pytorch to tensorrt, ExportedProgram, Dynamo graph break, use_explicit_typing, enabled_precisions, torch_tensorrt.Input, min_block_size, truncate_double, tensorrt-cu13, version pinning, version compatibility. Adjacent skills: `trt-onnx-quickstart`, `trt-cpp-runtime-quickstart`. LLM token generation belongs in TensorRT-LLM.

来源信息

仓库
NVIDIA/TensorRT
最近来源活动
2026年6月24日 21:24
检测到的 SKILL.md 语言
英语
星标
13,405
分支
2,414

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
trt-torch-quickstart
description
Compile a PyTorch model to a TensorRT engine via Torch-TensorRT — AOT or JIT — under the new strong-typing default. Use when the user compiles PyTorch to TensorRT without ONNX, hits "enabled_precisions should not be used when use_explicit_typing=True", sees Dynamo graph breaks or PyTorch fallback, debugs ABI errors at import torch_tensorrt, or needs the compatible torch / torch_tensorrt / tensorrt-cu13 version pins for TensorRT 11. Triggers: torch_tensorrt, torch_tensorrt.dynamo.compile, torch.compile backend torch_tensorrt, pytorch to tensorrt, ExportedProgram, Dynamo graph break, use_explicit_typing, enabled_precisions, torch_tensorrt.Input, min_block_size, truncate_double, tensorrt-cu13, version pinning, version compatibility. Adjacent skills: `trt-onnx-quickstart`, `trt-cpp-runtime-quickstart`. LLM token generation belongs in TensorRT-LLM.
license
Apache-2.0
metadata
{"author":"NVIDIA Corporation","version":"1.0","tags":["torch-tensorrt","dynamo","pytorch","quickstart","fp16"]}
# Torch-TensorRT Quickstart Convert a PyTorch `nn.Module` to a TensorRT engine using `torch_tensorrt` (the [Torch-TensorRT](https://github.com/pytorch/TensorRT) frontend). Covers the AOT path (for production and C++ deploy) and the JIT path (for Python-only inference). ## When to Use | Scenario | Use this skill? | |----------|-----------------| | PyTorch `nn.Module`; want a TensorRT engine without writing an ONNX intermediate | Yes | | Model uses ops that don't export cleanly to ONNX (custom autograd, dynamic control flow) | Yes | | Want Torch-TensorRT's automatic fallback of unsupported subgraphs to PyTorch | Yes | | Need a serialized engine for C++ deploy from a PyTorch source | Yes — use AOT path here, then `trt-cpp-runtime-quickstart` for the C++ load | | Have a working ONNX file already | No — use `trt-onnx-quickstart` | | LLM token generation (Llama, Mistral, Qwen text gen) | **No** — route to [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM) | | Have a `.plan` file already and want to run it from C++ | No — use `trt-cpp-runtime-quickstart` | | Migrating an existing weakly-typed TRT network to strongly-typed | No — use `trt-strong-typing-migration` | ## Prerequisites Torch-TensorRT versions are tightly coupled to a (torch, tensorrt-cu13, CUDA) triple; mismatches produce ABI errors at `import torch_tensorrt`. **Pin matrix source of truth:** the [pytorch/TensorRT releases page](https://github.com/pytorch/TensorRT/releases) — each release lists the exact `torch` / `tensorrt` / CUDA versions it was built against. Do not invent pins from memory. For TensorRT 11.0: | Component | Required | Notes | |-----------|----------|-------| | TensorRT | 11.x (`tensorrt-cu13` wheel) | Mixing `-cu12` and `-cu13` wheels breaks imports. | | CUDA toolkit | 13.x | Driver R590+. | | Python | ≥ 3.10 | TRT 11 dropped 3.9 and earlier. | | `torch` | Match the `torch_tensorrt` release notes for the chosen `torch_tensorrt` version. | | | `torch_tensorrt` | The release matching the TRT 11.0 RC — see [pytorch/TensorRT releases](https://github.com/pytorch/TensorRT/releases). | | **Recommended environment**: NGC TensorRT container with PyTorch (`nvcr.io/nvidia/pytorch:<tag>` or `nvcr.io/nvidia/tensorrt:<tag>` with `torch_tensorrt` pip-installed on top). Run with `--gpus all`. Verification: ```bash python3 -c "import torch, torch_tensorrt, tensorrt; print(torch.__version__, torch_tensorrt.__version__, tensorrt.__version__)" ``` ## Step 1 — Load and prepare the model Use a `torch.nn.Module` in eval mode. Torch-TensorRT will trace through it. ```python import torch import torchvision.models as models model = models.resnet50(weights=None).eval().cuda() example = torch.randn(1, 3, 224, 224, device="cuda") ``` Notes: - `weights=None` skips the download — fine for shape/perf testing. For accuracy work, load real weights. - Model must be on CUDA before compile. Torch-TensorRT does not move it for you. - `.eval()` matters: BatchNorm and Dropout behave differently in train mode and can produce different engines. ## Step 2 — Compile to a TensorRT engine (AOT) Two compile paths — pick by deployment target: | Goal | Path | API | |------|------|-----| | Serialized engine (production, C++ deploy, reuse) | **AOT** — this section | `torch_tensorrt.dynamo.compile` → `torch_tensorrt.save` | | In-process Python callable only (no serialized engine) | **JIT** — end of this section | `torch.compile(backend="torch_tensorrt")` | The AOT path uses `torch_tensorrt.dynamo.compile` and returns a serializable `ExportedProgram`. **Important — strong typing is the default in torch_tensorrt ≥ 2.12.** With `use_explicit_typing=True` (the default), engine precision is **inferred from the exported model's dtype** — passing `enabled_precisions={torch.float16}` raises `AssertionError`. To compile in FP16, cast the model and example tensor to FP16 before exporting: ```python import torch import torch_tensorrt model = MyModel().eval().cuda().half() # cast to FP16 example = torch.randn(1, 3, 224, 224, device="cuda", dtype=torch.float16) trt_gm = torch_tensorrt.dynamo.compile( torch.export.export(model, (example,)), inputs=[example], # No enabled_precisions — precision comes from the model dtype. truncate_double=True, min_block_size=1, ) # Serialize for later / C++ loading — use torch_tensorrt.save, NOT raw bytes. torch_tensorrt.save(trt_gm, "resnet50_trt.ep", inputs=[example]) ``` **Do not extract raw engine bytes via `submod.engine` and write them with `open(...).write(...)`.** That bypasses Torch-TensorRT's metadata wrapper: the blob will not round-trip through `torch_tensorrt.load(...)` and silently drops the dispatch graph that handles partial-fallback subgraphs. `torch_tensorrt.save(trt_gm, path, inputs=...)` is the only supported serialization path. For mixed precision or to override the model dtype, set `use_explicit_typing=False` and `enabled_precisions` applies as before (the weakly-typed path, deprecated in TRT 11): ```python trt_gm = torch_tensorrt.dynamo.compile( torch.export.export(model, (example,)), inputs=[example], use_explicit_typing=False, # weakly-typed (deprecated) enabled_precisions={torch.float16, torch.float32}, truncate_double=True, ) ``` Key arguments: - `truncate_double=True`: silently downcasts FP64 constants. Without it, any FP64 op forces a partition boundary. - `min_block_size`: smallest subgraph (in node count) worth handing to TRT. `1` is aggressive; default `5` avoids tiny TRT subgraphs that don't pay back their launch overhead. - `workspace_size`: bytes of scratch memory the TRT builder can use. Leave unset to let TRT decide. **JIT alternative (Python-only inference):** if you just want a callable and not a serialized engine, use `torch.compile` with the Torch-TensorRT backend. Under the strong-typing default, precision comes from the model dtype — `.half()` the model for FP16 rather than passing `enabled_precisions`: ```python model = model.half() # FP16 inferred from model dtype (strong typing default) example = example.half() trt_model = torch.compile(model, backend="torch_tensorrt") out = trt_model(example) # compiles lazily on the first call, then runs through TRT in-process ``` This skips `torch.export` and gives a `torch.compile`-wrapped callable. It cannot be loaded from C++ — use the AOT path above if you need that. ## Step 3 — Dynamic shapes Wrap inputs in `torch_tensorrt.Input` with `min_shape`/`opt_shape`/`max_shape`: ```python dynamic_input = torch_tensorrt.Input( min_shape=(1, 3, 224, 224), opt_shape=(8, 3, 224, 224), max_shape=(32, 3, 224, 224), dtype=torch.float16, ) trt_gm = torch_tensorrt.dynamo.compile( torch.export.export(model, (example,), dynamic_shapes={"x": {0: torch.export.Dim("batch", min=1, max=32)}}), inputs=[dynamic_input], # Strong typing: FP16 comes from the input/model dtype, not enabled_precisions. ) ``` Pitfalls: - The `dynamic_shapes=` argument to `torch.export.export` and the `Input` ranges must agree. A mismatch produces a builder error 2–3 minutes into compilation, not at export time. - `opt_shape` is what TRT tunes kernels for. Set it to the most common runtime shape, not the midpoint. - Only mark dimensions dynamic that actually vary at runtime; unnecessary dynamism degrades performance. ## Step 4 — Run inference and verify Raw-tensor comparison (`assert_close`) is fine for FP32 but **misleading for FP16** — a few outlier positions exceed the tolerance even when downstream behavior is identical. Use a **semantic check** appropriate to the model type: ```python with torch.inference_mode(): torch_out = model(example) trt_out = trt_gm(example) ``` **Image classification** — top-1 (or top-5) class match, plus mean-softmax-distance: ```python assert torch.equal(torch_out.argmax(-1), trt_out.argmax(-1)), "top-1 mismatch" mean_prob_diff = (torch.softmax(torch_out.float(), -1) - torch.softmax(trt_out.float(), -1)).abs().mean() assert mean_prob_diff < 1e-3 ``` **Sentence / token embeddings** — cosine similarity per token, mean across the batch: ```python cos = torch.nn.functional.cosine_similarity(torch_out.flatten(0, -2), trt_out.flatten(0, -2), dim=-1) assert cos.mean() > 0.999 ``` **Detection / regression heads** — bounded raw-tensor closeness on the meaningful sub-tensor (e.g., bbox coordinates), softmax check on the class logits. **FP32 sanity** — for any model, an FP32 (no `.half()`) run should pass `torch.testing.assert_close(trt_out, torch_out, rtol=1e-4, atol=1e-4)`. If that fails, the issue is in the compilation, not numeric precision. ## Loading the serialized engine **From Python**: ```python import torch_tensorrt loaded = torch_tensorrt.load("resnet50_trt.ep").module() out = loaded(example) ``` **From C++**: this skill does NOT cover C++ loading. The `.ep` file `torch_tensorrt.save` produces by default is a `torch.export` archive for the **Python** `torch_tensorrt.load(...)` path — it is *not* directly consumable by the plain TensorRT C++ runtime (`IRuntime` / `deserializeCudaEngine`), which expects a serialized TensorRT engine (`.plan`). Two supported C++ routes: - Save with `output_format="torchscript"` and deploy the TorchScript module with libtorch + the Torch-TensorRT C++ runtime. - If you only need the raw TensorRT engine in C++, build it through the ONNX path (`trt-onnx-quickstart`) and load the resulting `.plan` with `trt-cpp-runtime-quickstart` (modern `IRuntime` + `enqueueV3` + `setTensorAddress`). Do not inline a C++ snippet here — it will diverge from the canonical pattern. ## Common issues **`RuntimeError: Trying to create tensor with negative dimension`** during export — the model has a shape-dependent control flow path that `torch.export` can't trace. Either rewrite with `torch.cond` / `torch.where`, or fall back to `ir="dynamo"` + `min_block_size=1` so the unsupported region runs in PyTorch. **`Unsupported operator` warnings** — Torch-TensorRT partitions around them and runs those nodes in PyTorch. Set `require_full_compilation=True` to turn this into an error; use during development to find what's actually falling back. ## Diagnosing excessive PyTorch fallback If the compile completes but most of the model fell back to PyTorch (only a few subgraphs run on TRT), three knobs in order: 1. **Identify what fell back.** Run with `TORCH_LOGS="graph_breaks"` and `require_full_compilation=True` to escalate fallbacks to errors that name the offending op. Without this you don't know what the autotuner rejected. ```bash TORCH_LOGS="graph_breaks" python3 your_compile.py ``` 2. **Reconsider `min_block_size`.** This is a real trade-off — not just a knob. - Default `min_block_size=5`: Torch-TensorRT only hands a subgraph to TRT if it has ≥5 nodes. Tiny TRT subgraphs cost more in kernel-launch overhead than they save. - `min_block_size=1`: aggressive — every supported op goes to TRT, even single-node subgraphs. Useful to see what's *theoretically* supported, but commonly slower at inference due to the per-subgraph launch tax. - Recommended: leave at default `5` for production; drop to `1` only during diagnosis to see maximum TRT coverage. 3. **Look for shape-dependent control flow.** `torch.export` traces only one branch of `if x.shape[0] > 0:` style code; rewrite with `torch.where`, `torch.cond`, or lift the condition out of the model. The trace error names the offending op. If fallback persists after all three, you have a genuine unsupported op — write a converter (see Torch-TensorRT upstream docs) or switch to the ONNX path (`trt-onnx-quickstart`). **Engine builds but output is garbage** — almost always a dtype issue. Check: 1. Model/input dtype matches your pipeline — under strong typing precision follows the model dtype (`.half()` for FP16); `enabled_precisions` applies only under weak typing (`use_explicit_typing=False`). 2. `truncate_double=True` if the model has any FP64 constants (common in positional encodings). 3. The model was `.eval()` before export. **Compile takes >10 minutes** — turn on the builder log to see what's going on: ```python import torch_tensorrt.logging as ttlog ttlog.set_reportable_log_level(ttlog.Level.Info) ``` Usually it's the autotuner exploring kernel variants for a heavy GEMM/conv. To cap exploration, set `workspace_size` smaller (less scratch → fewer candidates). **`ImportError: cannot import name 'XYZ' from 'torch_tensorrt'`** — version mismatch. Confirm the pin matrix; the `torch_tensorrt` Python API moves between minor versions. ## Numerical debugging If `assert_close` fails by more than ~5× tolerance: 1. Re-run in FP32 — drop the model's `.half()` (or under weak typing, `enabled_precisions={torch.float32}`). If that matches PyTorch, the issue is FP16 accumulator drift in a specific op — usually a softmax or LayerNorm. The pragmatic fix is to wrap the offending submodule in a module excluded from the compile (`min_block_size` won't help; explicit exclusion is needed). See the [Torch-TensorRT lowering guide](https://pytorch.org/TensorRT/) for the version-specific exclusion API. 2. Sanity-check at FP32 first, then re-introduce FP16 and bisect — almost always reveals one offending op. 3. For FP8: check that the calibration distribution actually covers the runtime distribution. FP8 has no headroom for outliers. See `trt-strong-typing-migration` for the broader weak-vs-strong typing discussion. By default Torch-TensorRT produces strongly-typed engines in TRT 11.0 — types inferred from the exported program — but you can override. ## What this skill is not - Not a guide to writing custom Torch-TensorRT converters. Use the upstream Torch-TensorRT docs for that. - Not for TensorRT-LLM / LLM inference — use the TRT-LLM `examples/` flow instead. - Not for QAT (quantization-aware training) — Torch-TensorRT consumes the QAT model but the training loop is upstream. ## References - Upstream Torch-TensorRT: https://pytorch.org/TensorRT/ - Version pin matrix: [pytorch/TensorRT releases](https://github.com/pytorch/TensorRT/releases) - Related skills: `trt-onnx-quickstart`, `trt-strong-typing-migration`, `trt-cpp-runtime-quickstart`
在 GitHub 查看