kernel-lens 1.3.0__tar.gz → 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/PKG-INFO +43 -10
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/README.md +38 -5
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/__init__.py +1 -1
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/backends/builder.py +15 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/backends/trt_gen.py +86 -41
- kernel_lens-2.0.1/kernel_lens/backends/trt_v3_gen.py +571 -0
- kernel_lens-2.0.1/kernel_lens/compiler/ast_analyzer.py +300 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/core.py +21 -3
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/runtime/engine.py +7 -3
- kernel_lens-2.0.1/kernel_lens/utils/env_check.py +265 -0
- kernel_lens-2.0.1/kernel_lens/utils/trt_headers.py +199 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens.egg-info/PKG-INFO +43 -10
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens.egg-info/SOURCES.txt +2 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens.egg-info/requires.txt +4 -4
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/pyproject.toml +10 -3
- kernel_lens-1.3.0/kernel_lens/compiler/ast_analyzer.py +0 -179
- kernel_lens-1.3.0/kernel_lens/utils/env_check.py +0 -107
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/LICENSE +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/backends/__init__.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/backends/ort_gen.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/__init__.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/interaction.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/manifest.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/onnx_exporter.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/compiler/tracer.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/config.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInfer.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferImpl.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferLegacyDims.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferPlugin.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferPluginBase.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferPluginUtils.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferRuntime.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferRuntimeBase.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferRuntimeCommon.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferRuntimePlugin.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/include/tensorrt/NvInferVersion.h +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/runtime/__init__.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/utils/__init__.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens/utils/deployment.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens.egg-info/dependency_links.txt +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/kernel_lens.egg-info/top_level.txt +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/setup.cfg +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_alignment_guard.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_architectural_fixes.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_conformance.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_edge_cases.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_fp8_gemm.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_fused_cross_entropy.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_fused_residual_rms.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_inplace.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_inplace_dtypes.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_int4_dequant_gemm.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_mamba_selective_scan.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_research_kernels.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_standalone.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_standalone_launch.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_standalone_ptx.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_tricky_triton_kernels.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_triton_vs_torch_compile.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_trt.py +0 -0
- {kernel_lens-1.3.0 → kernel_lens-2.0.1}/tests/test_unit_cpu.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kernel-lens
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: Compile PyTorch models with custom @triton.jit kernels into ONNX Runtime and TensorRT C++ plugins
|
|
5
5
|
Author-email: Justin Duc <justin.duc@galiad-research.com>
|
|
6
6
|
License: MIT License
|
|
@@ -52,12 +52,12 @@ Requires-Dist: onnx>=1.15.0
|
|
|
52
52
|
Provides-Extra: ort
|
|
53
53
|
Requires-Dist: onnxruntime-gpu>=1.17.0; extra == "ort"
|
|
54
54
|
Provides-Extra: trt
|
|
55
|
-
Requires-Dist: tensorrt<
|
|
56
|
-
Requires-Dist: tensorrt-cu12-libs
|
|
55
|
+
Requires-Dist: tensorrt<12.0.0,>=8.6.0; extra == "trt"
|
|
56
|
+
Requires-Dist: tensorrt-cu12-libs; extra == "trt"
|
|
57
57
|
Provides-Extra: all
|
|
58
58
|
Requires-Dist: onnxruntime-gpu>=1.17.0; extra == "all"
|
|
59
|
-
Requires-Dist: tensorrt<
|
|
60
|
-
Requires-Dist: tensorrt-cu12-libs
|
|
59
|
+
Requires-Dist: tensorrt<12.0.0,>=8.6.0; extra == "all"
|
|
60
|
+
Requires-Dist: tensorrt-cu12-libs; extra == "all"
|
|
61
61
|
Provides-Extra: bench
|
|
62
62
|
Requires-Dist: transformers>=4.40.0; extra == "bench"
|
|
63
63
|
Dynamic: license-file
|
|
@@ -86,7 +86,8 @@ Dynamic: license-file
|
|
|
86
86
|
|
|
87
87
|
**KernelLens** compiles a PyTorch model that contains custom `@triton.jit` kernels
|
|
88
88
|
into native C++ artifacts for **ONNX Runtime** (`OrtCustomOp`) and **NVIDIA
|
|
89
|
-
TensorRT
|
|
89
|
+
TensorRT 8.6 to 11** (`nvinfer1::IPluginV2DynamicExt`, and `nvinfer1::IPluginV3`
|
|
90
|
+
on TensorRT 10 and later). You write Triton in Python; it
|
|
90
91
|
emits the C++ plugin, builds the `.so`, and runs it with **zero-copy VRAM
|
|
91
92
|
binding** — no manual C++ and no Python in the serving path.
|
|
92
93
|
|
|
@@ -114,6 +115,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
|
|
|
114
115
|
- **Dynamic grids in C++** — launch-grid expressions are transpiled to C++
|
|
115
116
|
integer math over runtime shapes, so one plugin serves dynamic batch and
|
|
116
117
|
sequence lengths.
|
|
118
|
+
- **One package, several TensorRT versions** — the plugin interface is chosen
|
|
119
|
+
from the environment. TensorRT 10 deprecated the whole `IPluginV2*` hierarchy
|
|
120
|
+
and TensorRT 11 removed it, so `plugin_api="auto"` (the default) emits
|
|
121
|
+
`IPluginV3` plugins where the runtime supports them and `IPluginV2DynamicExt`
|
|
122
|
+
plugins otherwise. This spans TensorRT 8.6 through 10.x today; TensorRT 11+
|
|
123
|
+
works when you point `TENSORRT_INCLUDE_DIR` at matching headers.
|
|
117
124
|
- **Shape-generic engines** — `kl.compile(..., dynamic_shapes=True)` exports the
|
|
118
125
|
leading dimension as a symbolic axis, so a single engine serves any size in a
|
|
119
126
|
declared range via a TensorRT optimization profile. Verified on Blackwell
|
|
@@ -139,9 +146,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
|
|
|
139
146
|
> conformance patterns and the quantized GEMMs, on both backends; two
|
|
140
147
|
> multi-operator fusions land just above zero and are reported as such. Keeping
|
|
141
148
|
> the kernel pays when the baseline leaves the graph unfused and breaks even when
|
|
142
|
-
> it already fuses.
|
|
143
|
-
> [
|
|
144
|
-
>
|
|
149
|
+
> it already fuses. A TensorRT-LLM backend is out of scope; the
|
|
150
|
+
> [design note](docs/assets/data/a100/trtllm_backend_design.md) records what
|
|
151
|
+
> integrating one would take. The kernels themselves are usable there — they are
|
|
152
|
+
> ordinary `@triton.jit` functions, and an A100 measurement confirmed a KernelLens
|
|
153
|
+
> RMSNorm is bit-identical to the flashinfer kernel TensorRT-LLM already uses
|
|
154
|
+
> (`0.00e+00`). The quantized GEMMs are validated on ONNX Runtime only. Full methodology
|
|
145
155
|
> and every raw JSON are under [`docs/assets/data/`](docs/assets/data/).
|
|
146
156
|
|
|
147
157
|
## Installation
|
|
@@ -157,11 +167,34 @@ pip install kernel-lens[all] # both
|
|
|
157
167
|
Triton ≥ 2.1, and `nvcc` + `g++` on `PATH`. TensorRT must be `< 11` (the
|
|
158
168
|
generator emits `IPluginV2DynamicExt`).
|
|
159
169
|
|
|
170
|
+
**TensorRT versions.** Handled automatically. The pip TensorRT wheels ship **no
|
|
171
|
+
headers**, so KernelLens fetches the set matching the installed runtime from the
|
|
172
|
+
TensorRT OSS repository and caches it under `~/.kernel_lens_headers/<major>.<minor>`;
|
|
173
|
+
when the headers it already has match the runtime major, nothing is fetched. If
|
|
174
|
+
the download is unavailable the fallback is the bundled set, and a
|
|
175
|
+
header/runtime major mismatch is then reported instead of crashing inside
|
|
176
|
+
TensorRT. `plugin_api="auto"` picks the interface from the runtime:
|
|
177
|
+
|
|
178
|
+
| TensorRT | `IPluginV2*` | `IPluginV3` | emitted |
|
|
179
|
+
| :--- | :--- | :--- | :--- |
|
|
180
|
+
| < 10 (8.6, 9.x) | present | absent | `v2` |
|
|
181
|
+
| 10.x | deprecated | present | `v3` |
|
|
182
|
+
| 11+ | **removed** | present | `v3` |
|
|
183
|
+
|
|
184
|
+
Verified on TensorRT 10.16 and 11.3, both 16/16 on the conformance suite. Force
|
|
185
|
+
a choice with `plugin_api="v2"` / `"v3"`, or the `KERNEL_LENS_PLUGIN_API`
|
|
186
|
+
environment variable. To supply headers yourself — offline installs, or a TensorRT
|
|
187
|
+
build the OSS repository does not track — set `TENSORRT_INCLUDE_DIR`, or
|
|
188
|
+
`KERNEL_LENS_FETCH_HEADERS=0` to disable fetching entirely.
|
|
189
|
+
|
|
160
190
|
**Environment:** `KERNEL_LENS_CACHE_DIR` (put it on a persistent volume so the
|
|
161
191
|
`.so` / `.engine` artifacts survive `kl.load`), `KERNEL_LENS_CCBIN` (host
|
|
162
192
|
compiler for `nvcc` — CUDA toolkits before 12.9 reject GCC 13's exception
|
|
163
193
|
specifiers, so set it to `g++-12` there), `KERNEL_LENS_DEBUG` (or `KL_VERBOSE`),
|
|
164
|
-
`TENSORRT_INCLUDE_DIR
|
|
194
|
+
`TENSORRT_INCLUDE_DIR` (override the TensorRT headers),
|
|
195
|
+
`KERNEL_LENS_HEADER_CACHE` (where fetched TensorRT headers are kept),
|
|
196
|
+
`KERNEL_LENS_FETCH_HEADERS=0` (disable fetching),
|
|
197
|
+
`KERNEL_LENS_PLUGIN_API` (`auto`, `v2` or `v3`), and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
|
|
165
198
|
above 2 GB from disk rather than from a memory buffer (opt-in; see the
|
|
166
199
|
[changelog](CHANGELOG.md)).
|
|
167
200
|
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
**KernelLens** compiles a PyTorch model that contains custom `@triton.jit` kernels
|
|
24
24
|
into native C++ artifacts for **ONNX Runtime** (`OrtCustomOp`) and **NVIDIA
|
|
25
|
-
TensorRT
|
|
25
|
+
TensorRT 8.6 to 11** (`nvinfer1::IPluginV2DynamicExt`, and `nvinfer1::IPluginV3`
|
|
26
|
+
on TensorRT 10 and later). You write Triton in Python; it
|
|
26
27
|
emits the C++ plugin, builds the `.so`, and runs it with **zero-copy VRAM
|
|
27
28
|
binding** — no manual C++ and no Python in the serving path.
|
|
28
29
|
|
|
@@ -50,6 +51,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
|
|
|
50
51
|
- **Dynamic grids in C++** — launch-grid expressions are transpiled to C++
|
|
51
52
|
integer math over runtime shapes, so one plugin serves dynamic batch and
|
|
52
53
|
sequence lengths.
|
|
54
|
+
- **One package, several TensorRT versions** — the plugin interface is chosen
|
|
55
|
+
from the environment. TensorRT 10 deprecated the whole `IPluginV2*` hierarchy
|
|
56
|
+
and TensorRT 11 removed it, so `plugin_api="auto"` (the default) emits
|
|
57
|
+
`IPluginV3` plugins where the runtime supports them and `IPluginV2DynamicExt`
|
|
58
|
+
plugins otherwise. This spans TensorRT 8.6 through 10.x today; TensorRT 11+
|
|
59
|
+
works when you point `TENSORRT_INCLUDE_DIR` at matching headers.
|
|
53
60
|
- **Shape-generic engines** — `kl.compile(..., dynamic_shapes=True)` exports the
|
|
54
61
|
leading dimension as a symbolic axis, so a single engine serves any size in a
|
|
55
62
|
declared range via a TensorRT optimization profile. Verified on Blackwell
|
|
@@ -75,9 +82,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
|
|
|
75
82
|
> conformance patterns and the quantized GEMMs, on both backends; two
|
|
76
83
|
> multi-operator fusions land just above zero and are reported as such. Keeping
|
|
77
84
|
> the kernel pays when the baseline leaves the graph unfused and breaks even when
|
|
78
|
-
> it already fuses.
|
|
79
|
-
> [
|
|
80
|
-
>
|
|
85
|
+
> it already fuses. A TensorRT-LLM backend is out of scope; the
|
|
86
|
+
> [design note](docs/assets/data/a100/trtllm_backend_design.md) records what
|
|
87
|
+
> integrating one would take. The kernels themselves are usable there — they are
|
|
88
|
+
> ordinary `@triton.jit` functions, and an A100 measurement confirmed a KernelLens
|
|
89
|
+
> RMSNorm is bit-identical to the flashinfer kernel TensorRT-LLM already uses
|
|
90
|
+
> (`0.00e+00`). The quantized GEMMs are validated on ONNX Runtime only. Full methodology
|
|
81
91
|
> and every raw JSON are under [`docs/assets/data/`](docs/assets/data/).
|
|
82
92
|
|
|
83
93
|
## Installation
|
|
@@ -93,11 +103,34 @@ pip install kernel-lens[all] # both
|
|
|
93
103
|
Triton ≥ 2.1, and `nvcc` + `g++` on `PATH`. TensorRT must be `< 11` (the
|
|
94
104
|
generator emits `IPluginV2DynamicExt`).
|
|
95
105
|
|
|
106
|
+
**TensorRT versions.** Handled automatically. The pip TensorRT wheels ship **no
|
|
107
|
+
headers**, so KernelLens fetches the set matching the installed runtime from the
|
|
108
|
+
TensorRT OSS repository and caches it under `~/.kernel_lens_headers/<major>.<minor>`;
|
|
109
|
+
when the headers it already has match the runtime major, nothing is fetched. If
|
|
110
|
+
the download is unavailable the fallback is the bundled set, and a
|
|
111
|
+
header/runtime major mismatch is then reported instead of crashing inside
|
|
112
|
+
TensorRT. `plugin_api="auto"` picks the interface from the runtime:
|
|
113
|
+
|
|
114
|
+
| TensorRT | `IPluginV2*` | `IPluginV3` | emitted |
|
|
115
|
+
| :--- | :--- | :--- | :--- |
|
|
116
|
+
| < 10 (8.6, 9.x) | present | absent | `v2` |
|
|
117
|
+
| 10.x | deprecated | present | `v3` |
|
|
118
|
+
| 11+ | **removed** | present | `v3` |
|
|
119
|
+
|
|
120
|
+
Verified on TensorRT 10.16 and 11.3, both 16/16 on the conformance suite. Force
|
|
121
|
+
a choice with `plugin_api="v2"` / `"v3"`, or the `KERNEL_LENS_PLUGIN_API`
|
|
122
|
+
environment variable. To supply headers yourself — offline installs, or a TensorRT
|
|
123
|
+
build the OSS repository does not track — set `TENSORRT_INCLUDE_DIR`, or
|
|
124
|
+
`KERNEL_LENS_FETCH_HEADERS=0` to disable fetching entirely.
|
|
125
|
+
|
|
96
126
|
**Environment:** `KERNEL_LENS_CACHE_DIR` (put it on a persistent volume so the
|
|
97
127
|
`.so` / `.engine` artifacts survive `kl.load`), `KERNEL_LENS_CCBIN` (host
|
|
98
128
|
compiler for `nvcc` — CUDA toolkits before 12.9 reject GCC 13's exception
|
|
99
129
|
specifiers, so set it to `g++-12` there), `KERNEL_LENS_DEBUG` (or `KL_VERBOSE`),
|
|
100
|
-
`TENSORRT_INCLUDE_DIR
|
|
130
|
+
`TENSORRT_INCLUDE_DIR` (override the TensorRT headers),
|
|
131
|
+
`KERNEL_LENS_HEADER_CACHE` (where fetched TensorRT headers are kept),
|
|
132
|
+
`KERNEL_LENS_FETCH_HEADERS=0` (disable fetching),
|
|
133
|
+
`KERNEL_LENS_PLUGIN_API` (`auto`, `v2` or `v3`), and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
|
|
101
134
|
above 2 GB from disk rather than from a memory buffer (opt-in; see the
|
|
102
135
|
[changelog](CHANGELOG.md)).
|
|
103
136
|
|
|
@@ -249,6 +249,21 @@ def build_trt_plugin(trt_plugins_dir: str, cache_dir: str):
|
|
|
249
249
|
arch_flag = "-gencode=arch=compute_75,code=sm_75"
|
|
250
250
|
|
|
251
251
|
trt_inc_dirs = []
|
|
252
|
+
|
|
253
|
+
# Headers matching the installed TensorRT, fetched and cached on first
|
|
254
|
+
# use when the bundled set is a different major version. See
|
|
255
|
+
# utils/trt_headers.py for why this is necessary: the pip TensorRT
|
|
256
|
+
# wheels ship no headers at all.
|
|
257
|
+
try:
|
|
258
|
+
from ..utils.trt_headers import resolve as _resolve_headers
|
|
259
|
+
_hdr_dir, _hdr_reason = _resolve_headers()
|
|
260
|
+
from ..config import debug_print as _dp
|
|
261
|
+
_dp(f"[KernelLens] TensorRT headers: {_hdr_dir or 'bundled'} ({_hdr_reason})")
|
|
262
|
+
if _hdr_dir:
|
|
263
|
+
trt_inc_dirs.append(_hdr_dir)
|
|
264
|
+
except Exception:
|
|
265
|
+
pass
|
|
266
|
+
|
|
252
267
|
if os.environ.get("TENSORRT_INCLUDE_DIR"):
|
|
253
268
|
trt_inc_dirs.append(os.environ["TENSORRT_INCLUDE_DIR"])
|
|
254
269
|
user_trt_inc = os.path.expanduser("~/tensorrt_headers")
|
|
@@ -28,37 +28,31 @@ class TensorRTPluginGenerator:
|
|
|
28
28
|
self.plugin_namespace = plugin_namespace
|
|
29
29
|
self.plugin_version = plugin_version
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return "nvinfer1::DataType::kINT64"
|
|
57
|
-
elif 'int' in dtype_str:
|
|
58
|
-
return "nvinfer1::DataType::kINT32"
|
|
59
|
-
else:
|
|
60
|
-
return "nvinfer1::DataType::kFLOAT"
|
|
61
|
-
|
|
31
|
+
@staticmethod
|
|
32
|
+
def trt_datatype(dtype_obj: str) -> str:
|
|
33
|
+
"""Map a torch dtype onto the TensorRT DataType."""
|
|
34
|
+
dtype_str = str(dtype_obj).lower()
|
|
35
|
+
if 'float8' in dtype_str or 'fp8' in dtype_str or 'e4m3' in dtype_str or 'e5m2' in dtype_str:
|
|
36
|
+
return "nvinfer1::DataType::kFP8"
|
|
37
|
+
elif 'bool' in dtype_str:
|
|
38
|
+
return "nvinfer1::DataType::kBOOL"
|
|
39
|
+
elif 'uint8' in dtype_str or 'int8' in dtype_str or 'int4' in dtype_str or 'uint4' in dtype_str:
|
|
40
|
+
return "nvinfer1::DataType::kINT8"
|
|
41
|
+
elif 'bfloat16' in dtype_str or 'bf16' in dtype_str:
|
|
42
|
+
return "nvinfer1::DataType::kBF16"
|
|
43
|
+
elif 'float16' in dtype_str or 'half' in dtype_str:
|
|
44
|
+
return "nvinfer1::DataType::kHALF"
|
|
45
|
+
elif 'float' in dtype_str:
|
|
46
|
+
return "nvinfer1::DataType::kFLOAT"
|
|
47
|
+
elif 'int64' in dtype_str or 'long' in dtype_str:
|
|
48
|
+
return "nvinfer1::DataType::kINT64"
|
|
49
|
+
elif 'int' in dtype_str:
|
|
50
|
+
return "nvinfer1::DataType::kINT32"
|
|
51
|
+
else:
|
|
52
|
+
return "nvinfer1::DataType::kFLOAT"
|
|
53
|
+
@staticmethod
|
|
54
|
+
def supports_format_body(manifest: KernelManifest, tensor_prefix: str = "") -> str:
|
|
55
|
+
"""The supportsFormatCombination body, shared by both plugin emitters."""
|
|
62
56
|
in_args = [a for a in manifest.arguments if a.kind in ('input', 'inplace')]
|
|
63
57
|
|
|
64
58
|
# Enforce the dtype the kernel was compiled for, position by position.
|
|
@@ -67,7 +61,7 @@ class TensorRTPluginGenerator:
|
|
|
67
61
|
_ordered_in = [a for a in manifest.arguments if a.kind in ('input', 'inplace')]
|
|
68
62
|
_ordered_sc = [a for a in manifest.arguments if a.kind == 'scalar' and not getattr(a, 'is_constexpr', False)]
|
|
69
63
|
_ordered_out = [a for a in manifest.arguments if a.kind in ('output', 'inplace')]
|
|
70
|
-
_pos_types = [
|
|
64
|
+
_pos_types = [TensorRTPluginGenerator.trt_datatype(a.dtype) for a in (_ordered_in + _ordered_sc + _ordered_out)]
|
|
71
65
|
_pos_is_tensor = ([True] * len(_ordered_in) + [False] * len(_ordered_sc) + [True] * len(_ordered_out))
|
|
72
66
|
_types_cpp = ", ".join(_pos_types) if _pos_types else "nvinfer1::DataType::kFLOAT"
|
|
73
67
|
_is_tensor_cpp = ", ".join("true" if t else "false" for t in _pos_is_tensor) if _pos_is_tensor else "true"
|
|
@@ -96,7 +90,24 @@ class TensorRTPluginGenerator:
|
|
|
96
90
|
)
|
|
97
91
|
else:
|
|
98
92
|
supports_format_cxx = type_guard_cxx + "return inOut[pos].format == nvinfer1::TensorFormat::kLINEAR;"
|
|
99
|
-
|
|
93
|
+
# IPluginV3 hands supportsFormatCombination a DynamicPluginTensorDesc,
|
|
94
|
+
# whose fields live under .desc; V2 hands it a PluginTensorDesc directly.
|
|
95
|
+
if tensor_prefix:
|
|
96
|
+
supports_format_cxx = supports_format_cxx.replace("inOut[pos].", f"inOut[pos]{tensor_prefix}.")
|
|
97
|
+
return supports_format_cxx
|
|
98
|
+
|
|
99
|
+
def _generate_kernel_h(self, manifest: KernelManifest) -> str:
|
|
100
|
+
plugin_name = f"{manifest.kernel_name}Plugin"
|
|
101
|
+
|
|
102
|
+
constant_decls = []
|
|
103
|
+
for arg in manifest.arguments:
|
|
104
|
+
if arg.kind == 'scalar':
|
|
105
|
+
ctype = "float" if isinstance(arg.value, float) else "int"
|
|
106
|
+
constant_decls.append(f"{ctype} m_{arg.name};")
|
|
107
|
+
dynamic_members_cpp = "\n ".join(constant_decls)
|
|
108
|
+
|
|
109
|
+
get_trt_datatype = TensorRTPluginGenerator.trt_datatype
|
|
110
|
+
supports_format_cxx = TensorRTPluginGenerator.supports_format_body(manifest)
|
|
100
111
|
output_dim_cases = []
|
|
101
112
|
out_args = [a for a in manifest.arguments if a.kind in ('output', 'inplace')]
|
|
102
113
|
_dyn_axes = tuple(getattr(manifest, "dynamic_axes", ()) or ())
|
|
@@ -217,12 +228,15 @@ private:
|
|
|
217
228
|
'''
|
|
218
229
|
return textwrap.dedent(tpl).strip()
|
|
219
230
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
231
|
+
@staticmethod
|
|
232
|
+
def build_shared_body(manifest: KernelManifest, block_size: int):
|
|
233
|
+
"""Build the pieces the enqueue implementation needs.
|
|
234
|
+
|
|
235
|
+
Shared verbatim between the IPluginV2DynamicExt and the
|
|
236
|
+
IPluginV3 emitters: the PTX entry name, the kernelParams
|
|
237
|
+
assembly and the output-type dispatch are the same; only the
|
|
238
|
+
class hierarchy and the method signatures around them differ.
|
|
239
|
+
"""
|
|
226
240
|
scalars = [arg for arg in manifest.arguments if arg.kind == 'scalar']
|
|
227
241
|
nb_outputs = sum(1 for arg in manifest.arguments if arg.kind == 'output')
|
|
228
242
|
nb_outputs = max(1, nb_outputs)
|
|
@@ -388,10 +402,41 @@ private:
|
|
|
388
402
|
|
|
389
403
|
output_type_lines.append(f"if (index == {i}) return {trt_type};")
|
|
390
404
|
|
|
391
|
-
|
|
405
|
+
return {
|
|
406
|
+
"ptx_entry_name": ptx_entry_name,
|
|
407
|
+
"dynamic_args_cpp": "\n ".join(arg_setup_lines),
|
|
408
|
+
"dynamic_output_types": "\n ".join(output_type_lines),
|
|
409
|
+
"grid_x_cxx": grid_x_cxx,
|
|
410
|
+
"grid_y_cxx": grid_y_cxx,
|
|
411
|
+
"grid_z_cxx": grid_z_cxx,
|
|
412
|
+
"num_ptx_slots": num_ptx_slots,
|
|
413
|
+
"init_str": init_str,
|
|
414
|
+
"size_additions": size_additions,
|
|
415
|
+
"deserialize_cpp": deserialize_cpp,
|
|
416
|
+
"serialize_cpp": serialize_cpp,
|
|
417
|
+
"clone_cpp": clone_cpp,
|
|
418
|
+
}
|
|
392
419
|
|
|
393
|
-
|
|
420
|
+
def _generate_kernel_cu(self, manifest: KernelManifest) -> str:
|
|
421
|
+
plugin_name = f"{manifest.kernel_name}Plugin"
|
|
422
|
+
ptx_str = manifest.ptx
|
|
423
|
+
ptx_encoded = json.dumps(ptx_str)
|
|
424
|
+
block_size = (manifest.num_warps if manifest.num_warps > 0 else 4) * 32
|
|
394
425
|
|
|
426
|
+
shared = TensorRTPluginGenerator.build_shared_body(manifest, block_size)
|
|
427
|
+
ptx_entry_name = shared["ptx_entry_name"]
|
|
428
|
+
dynamic_args_cpp = shared["dynamic_args_cpp"]
|
|
429
|
+
dynamic_output_types = shared["dynamic_output_types"]
|
|
430
|
+
grid_x_cxx = shared["grid_x_cxx"]
|
|
431
|
+
grid_y_cxx = shared["grid_y_cxx"]
|
|
432
|
+
grid_z_cxx = shared["grid_z_cxx"]
|
|
433
|
+
num_ptx_slots = shared["num_ptx_slots"]
|
|
434
|
+
init_str = shared["init_str"]
|
|
435
|
+
size_additions = shared["size_additions"]
|
|
436
|
+
deserialize_cpp = shared["deserialize_cpp"]
|
|
437
|
+
serialize_cpp = shared["serialize_cpp"]
|
|
438
|
+
clone_cpp = shared["clone_cpp"]
|
|
439
|
+
|
|
395
440
|
tpl = f'''
|
|
396
441
|
#include "{manifest.kernel_name}Plugin.h"
|
|
397
442
|
#include <cuda.h>
|