kernel-lens 1.3.0__tar.gz → 2.0.0__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.
Files changed (61) hide show
  1. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/PKG-INFO +35 -6
  2. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/README.md +30 -1
  3. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/__init__.py +1 -1
  4. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/backends/builder.py +15 -0
  5. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/backends/trt_gen.py +86 -41
  6. kernel_lens-2.0.0/kernel_lens/backends/trt_v3_gen.py +571 -0
  7. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/core.py +21 -3
  8. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/runtime/engine.py +7 -3
  9. kernel_lens-2.0.0/kernel_lens/utils/env_check.py +265 -0
  10. kernel_lens-2.0.0/kernel_lens/utils/trt_headers.py +199 -0
  11. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens.egg-info/PKG-INFO +35 -6
  12. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens.egg-info/SOURCES.txt +2 -0
  13. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens.egg-info/requires.txt +4 -4
  14. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/pyproject.toml +10 -3
  15. kernel_lens-1.3.0/kernel_lens/utils/env_check.py +0 -107
  16. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/LICENSE +0 -0
  17. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/backends/__init__.py +0 -0
  18. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/backends/ort_gen.py +0 -0
  19. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/__init__.py +0 -0
  20. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/ast_analyzer.py +0 -0
  21. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/interaction.py +0 -0
  22. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/manifest.py +0 -0
  23. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/onnx_exporter.py +0 -0
  24. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/compiler/tracer.py +0 -0
  25. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/config.py +0 -0
  26. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInfer.h +0 -0
  27. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferImpl.h +0 -0
  28. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferLegacyDims.h +0 -0
  29. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferPlugin.h +0 -0
  30. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferPluginBase.h +0 -0
  31. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferPluginUtils.h +0 -0
  32. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferRuntime.h +0 -0
  33. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferRuntimeBase.h +0 -0
  34. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferRuntimeCommon.h +0 -0
  35. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferRuntimePlugin.h +0 -0
  36. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/include/tensorrt/NvInferVersion.h +0 -0
  37. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/runtime/__init__.py +0 -0
  38. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/utils/__init__.py +0 -0
  39. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens/utils/deployment.py +0 -0
  40. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens.egg-info/dependency_links.txt +0 -0
  41. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/kernel_lens.egg-info/top_level.txt +0 -0
  42. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/setup.cfg +0 -0
  43. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_alignment_guard.py +0 -0
  44. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_architectural_fixes.py +0 -0
  45. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_conformance.py +0 -0
  46. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_edge_cases.py +0 -0
  47. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_fp8_gemm.py +0 -0
  48. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_fused_cross_entropy.py +0 -0
  49. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_fused_residual_rms.py +0 -0
  50. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_inplace.py +0 -0
  51. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_inplace_dtypes.py +0 -0
  52. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_int4_dequant_gemm.py +0 -0
  53. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_mamba_selective_scan.py +0 -0
  54. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_research_kernels.py +0 -0
  55. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_standalone.py +0 -0
  56. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_standalone_launch.py +0 -0
  57. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_standalone_ptx.py +0 -0
  58. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_tricky_triton_kernels.py +0 -0
  59. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_triton_vs_torch_compile.py +0 -0
  60. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_trt.py +0 -0
  61. {kernel_lens-1.3.0 → kernel_lens-2.0.0}/tests/test_unit_cpu.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kernel-lens
3
- Version: 1.3.0
3
+ Version: 2.0.0
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<11.0.0,>=8.6.0; extra == "trt"
56
- Requires-Dist: tensorrt-cu12-libs<11.0.0; extra == "trt"
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<11.0.0,>=8.6.0; extra == "all"
60
- Requires-Dist: tensorrt-cu12-libs<11.0.0; extra == "all"
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
@@ -114,6 +114,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
114
114
  - **Dynamic grids in C++** — launch-grid expressions are transpiled to C++
115
115
  integer math over runtime shapes, so one plugin serves dynamic batch and
116
116
  sequence lengths.
117
+ - **One package, several TensorRT versions** — the plugin interface is chosen
118
+ from the environment. TensorRT 10 deprecated the whole `IPluginV2*` hierarchy
119
+ and TensorRT 11 removed it, so `plugin_api="auto"` (the default) emits
120
+ `IPluginV3` plugins where the runtime supports them and `IPluginV2DynamicExt`
121
+ plugins otherwise. This spans TensorRT 8.6 through 10.x today; TensorRT 11+
122
+ works when you point `TENSORRT_INCLUDE_DIR` at matching headers.
117
123
  - **Shape-generic engines** — `kl.compile(..., dynamic_shapes=True)` exports the
118
124
  leading dimension as a symbolic axis, so a single engine serves any size in a
119
125
  declared range via a TensorRT optimization profile. Verified on Blackwell
@@ -157,11 +163,34 @@ pip install kernel-lens[all] # both
157
163
  Triton ≥ 2.1, and `nvcc` + `g++` on `PATH`. TensorRT must be `< 11` (the
158
164
  generator emits `IPluginV2DynamicExt`).
159
165
 
166
+ **TensorRT versions.** Handled automatically. The pip TensorRT wheels ship **no
167
+ headers**, so KernelLens fetches the set matching the installed runtime from the
168
+ TensorRT OSS repository and caches it under `~/.kernel_lens_headers/<major>.<minor>`;
169
+ when the headers it already has match the runtime major, nothing is fetched. If
170
+ the download is unavailable the fallback is the bundled set, and a
171
+ header/runtime major mismatch is then reported instead of crashing inside
172
+ TensorRT. `plugin_api="auto"` picks the interface from the runtime:
173
+
174
+ | TensorRT | `IPluginV2*` | `IPluginV3` | emitted |
175
+ | :--- | :--- | :--- | :--- |
176
+ | < 10 (8.6, 9.x) | present | absent | `v2` |
177
+ | 10.x | deprecated | present | `v3` |
178
+ | 11+ | **removed** | present | `v3` |
179
+
180
+ Verified on TensorRT 10.16 and 11.3, both 16/16 on the conformance suite. Force
181
+ a choice with `plugin_api="v2"` / `"v3"`, or the `KERNEL_LENS_PLUGIN_API`
182
+ environment variable. To supply headers yourself — offline installs, or a TensorRT
183
+ build the OSS repository does not track — set `TENSORRT_INCLUDE_DIR`, or
184
+ `KERNEL_LENS_FETCH_HEADERS=0` to disable fetching entirely.
185
+
160
186
  **Environment:** `KERNEL_LENS_CACHE_DIR` (put it on a persistent volume so the
161
187
  `.so` / `.engine` artifacts survive `kl.load`), `KERNEL_LENS_CCBIN` (host
162
188
  compiler for `nvcc` — CUDA toolkits before 12.9 reject GCC 13's exception
163
189
  specifiers, so set it to `g++-12` there), `KERNEL_LENS_DEBUG` (or `KL_VERBOSE`),
164
- `TENSORRT_INCLUDE_DIR`, and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
190
+ `TENSORRT_INCLUDE_DIR` (override the TensorRT headers),
191
+ `KERNEL_LENS_HEADER_CACHE` (where fetched TensorRT headers are kept),
192
+ `KERNEL_LENS_FETCH_HEADERS=0` (disable fetching),
193
+ `KERNEL_LENS_PLUGIN_API` (`auto`, `v2` or `v3`), and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
165
194
  above 2 GB from disk rather than from a memory buffer (opt-in; see the
166
195
  [changelog](CHANGELOG.md)).
167
196
 
@@ -50,6 +50,12 @@ compiled_model.run(inputs, backend="onnx"|"tensorrt")
50
50
  - **Dynamic grids in C++** — launch-grid expressions are transpiled to C++
51
51
  integer math over runtime shapes, so one plugin serves dynamic batch and
52
52
  sequence lengths.
53
+ - **One package, several TensorRT versions** — the plugin interface is chosen
54
+ from the environment. TensorRT 10 deprecated the whole `IPluginV2*` hierarchy
55
+ and TensorRT 11 removed it, so `plugin_api="auto"` (the default) emits
56
+ `IPluginV3` plugins where the runtime supports them and `IPluginV2DynamicExt`
57
+ plugins otherwise. This spans TensorRT 8.6 through 10.x today; TensorRT 11+
58
+ works when you point `TENSORRT_INCLUDE_DIR` at matching headers.
53
59
  - **Shape-generic engines** — `kl.compile(..., dynamic_shapes=True)` exports the
54
60
  leading dimension as a symbolic axis, so a single engine serves any size in a
55
61
  declared range via a TensorRT optimization profile. Verified on Blackwell
@@ -93,11 +99,34 @@ pip install kernel-lens[all] # both
93
99
  Triton ≥ 2.1, and `nvcc` + `g++` on `PATH`. TensorRT must be `< 11` (the
94
100
  generator emits `IPluginV2DynamicExt`).
95
101
 
102
+ **TensorRT versions.** Handled automatically. The pip TensorRT wheels ship **no
103
+ headers**, so KernelLens fetches the set matching the installed runtime from the
104
+ TensorRT OSS repository and caches it under `~/.kernel_lens_headers/<major>.<minor>`;
105
+ when the headers it already has match the runtime major, nothing is fetched. If
106
+ the download is unavailable the fallback is the bundled set, and a
107
+ header/runtime major mismatch is then reported instead of crashing inside
108
+ TensorRT. `plugin_api="auto"` picks the interface from the runtime:
109
+
110
+ | TensorRT | `IPluginV2*` | `IPluginV3` | emitted |
111
+ | :--- | :--- | :--- | :--- |
112
+ | < 10 (8.6, 9.x) | present | absent | `v2` |
113
+ | 10.x | deprecated | present | `v3` |
114
+ | 11+ | **removed** | present | `v3` |
115
+
116
+ Verified on TensorRT 10.16 and 11.3, both 16/16 on the conformance suite. Force
117
+ a choice with `plugin_api="v2"` / `"v3"`, or the `KERNEL_LENS_PLUGIN_API`
118
+ environment variable. To supply headers yourself — offline installs, or a TensorRT
119
+ build the OSS repository does not track — set `TENSORRT_INCLUDE_DIR`, or
120
+ `KERNEL_LENS_FETCH_HEADERS=0` to disable fetching entirely.
121
+
96
122
  **Environment:** `KERNEL_LENS_CACHE_DIR` (put it on a persistent volume so the
97
123
  `.so` / `.engine` artifacts survive `kl.load`), `KERNEL_LENS_CCBIN` (host
98
124
  compiler for `nvcc` — CUDA toolkits before 12.9 reject GCC 13's exception
99
125
  specifiers, so set it to `g++-12` there), `KERNEL_LENS_DEBUG` (or `KL_VERBOSE`),
100
- `TENSORRT_INCLUDE_DIR`, and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
126
+ `TENSORRT_INCLUDE_DIR` (override the TensorRT headers),
127
+ `KERNEL_LENS_HEADER_CACHE` (where fetched TensorRT headers are kept),
128
+ `KERNEL_LENS_FETCH_HEADERS=0` (disable fetching),
129
+ `KERNEL_LENS_PLUGIN_API` (`auto`, `v2` or `v3`), and `KERNEL_LENS_STREAM_READER=1` to deserialize engines
101
130
  above 2 GB from disk rather than from a memory buffer (opt-in; see the
102
131
  [changelog](CHANGELOG.md)).
103
132
 
@@ -7,7 +7,7 @@ from .config import set_verbose, is_verbose
7
7
 
8
8
 
9
9
 
10
- __version__ = "1.3.0"
10
+ __version__ = "2.0.0"
11
11
 
12
12
  __all__ = [
13
13
  "compile",
@@ -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
- def _generate_kernel_h(self, manifest: KernelManifest) -> str:
32
- plugin_name = f"{manifest.kernel_name}Plugin"
33
-
34
- constant_decls = []
35
- for arg in manifest.arguments:
36
- if arg.kind == 'scalar':
37
- ctype = "float" if isinstance(arg.value, float) else "int"
38
- constant_decls.append(f"{ctype} m_{arg.name};")
39
- dynamic_members_cpp = "\n ".join(constant_decls)
40
-
41
- def get_trt_datatype(dtype_obj):
42
- dtype_str = str(dtype_obj).lower()
43
- if 'float8' in dtype_str or 'fp8' in dtype_str or 'e4m3' in dtype_str or 'e5m2' in dtype_str:
44
- return "nvinfer1::DataType::kFP8"
45
- elif 'bool' in dtype_str:
46
- return "nvinfer1::DataType::kBOOL"
47
- elif 'uint8' in dtype_str or 'int8' in dtype_str or 'int4' in dtype_str or 'uint4' in dtype_str:
48
- return "nvinfer1::DataType::kINT8"
49
- elif 'bfloat16' in dtype_str or 'bf16' in dtype_str:
50
- return "nvinfer1::DataType::kBF16"
51
- elif 'float16' in dtype_str or 'half' in dtype_str:
52
- return "nvinfer1::DataType::kHALF"
53
- elif 'float' in dtype_str:
54
- return "nvinfer1::DataType::kFLOAT"
55
- elif 'int64' in dtype_str or 'long' in dtype_str:
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 = [get_trt_datatype(a.dtype) for a in (_ordered_in + _ordered_sc + _ordered_out)]
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
- def _generate_kernel_cu(self, manifest: KernelManifest) -> str:
221
- plugin_name = f"{manifest.kernel_name}Plugin"
222
- ptx_str = manifest.ptx
223
- ptx_encoded = json.dumps(ptx_str)
224
- block_size = (manifest.num_warps if manifest.num_warps > 0 else 4) * 32
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
- dynamic_output_types = "\n ".join(output_type_lines)
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
- dynamic_args_cpp = "\n ".join(arg_setup_lines)
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>