tensoracle 1.4.0__tar.gz → 1.6.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.
- {tensoracle-1.4.0 → tensoracle-1.6.0}/PKG-INFO +34 -16
- {tensoracle-1.4.0 → tensoracle-1.6.0}/README.md +33 -15
- tensoracle-1.6.0/docs/cpp-python-repositories.md +65 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/index.md +29 -3
- {tensoracle-1.4.0 → tensoracle-1.6.0}/mkdocs.yml +1 -1
- {tensoracle-1.4.0 → tensoracle-1.6.0}/pyproject.toml +4 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_build.py +11 -6
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_cache.py +39 -73
- tensoracle-1.6.0/src/tensoracle/_cache_format.py +78 -0
- tensoracle-1.6.0/src/tensoracle/_cli.py +250 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_version.py +2 -2
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_build.py +31 -6
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_cache.py +2 -2
- tensoracle-1.6.0/tests/test_cache_cli.py +392 -0
- tensoracle-1.6.0/tests/test_cache_management.py +198 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_distribution.py +46 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_precision.py +2 -6
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_weight_hash.py +2 -1
- tensoracle-1.4.0/docs/cpp-python-repositories.md +0 -199
- {tensoracle-1.4.0 → tensoracle-1.6.0}/.gitignore +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/LICENSE +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/build_backend.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/CMakeLists.txt +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/cmake/TensoracleCubinPlugin.cmake +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/cmake/TensoracleCuda.cmake +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/include/tensoracle/cubin_plugin.hpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/src/cubin_plugin.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/cpp/tests/core.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/api/bundle.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/api/index.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/api/producer.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/optimization.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/precision.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/docs/tensorrt-sdk.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/CMakeLists.txt +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/README.md +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/bundle.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/bundle.json +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm120/bias.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm120/dot.specialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm120/dot.tf32-control.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm120/dot.unspecialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm120/scale.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm86/bias.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm86/dot.specialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm86/dot.tf32-control.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm86/dot.unspecialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm86/scale.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm89/bias.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm89/dot.specialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm89/dot.tf32-control.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm89/dot.unspecialized.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/bundle/cubins/sm89/scale.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/example_cubin_plugin/__init__.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/example_cubin_plugin/weights.safetensors +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/kernels.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/plugin.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/examples/cubin_plugin/pyproject.toml +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/__init__.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_comparison.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_execution.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_memory.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/_plugins.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/bundle.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/convert.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/src/tensoracle/producer.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/build_memory_runtime.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubin_io/check.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubin_io/kernels.cu +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubin_io/plugin.cpp +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubins/ptxas-12.9.86/sm120.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubins/ptxas-12.9.86/sm86.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/cubins/ptxas-12.9.86/sm89.cubin +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/example_runtime.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/native/CMakeLists.txt +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/native/export.h +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/native_build.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/plugin_io_runtime.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/precision_runtime.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_build_memory.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_bundle.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_cmake_cuda.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_cmake_plugin.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_comparison.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_convert.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_cpp_core.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_cuda_graphs.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_engine_io.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_example_plugin.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_execution.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_gpu_cache.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_plugin_io.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_plugins.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_producer.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/tests/test_shape_tensor_outputs.py +0 -0
- {tensoracle-1.4.0 → tensoracle-1.6.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tensoracle
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Build, save, reuse, and execute TensorRT engines from safetensors weights
|
|
5
5
|
Project-URL: documentation, https://sync-dev-org.github.io/tensoracle/
|
|
6
6
|
Project-URL: repository, https://github.com/sync-dev-org/tensoracle
|
|
@@ -64,7 +64,7 @@ The supported targets are Linux x86_64 (including WSL2) and Windows x86_64, Tens
|
|
|
64
64
|
|
|
65
65
|
Follow the [four-stage optimization workflow](https://github.com/sync-dev-org/tensoracle/blob/main/docs/optimization.md) to establish output quality, evaluate lower precision and plugins, and measure speed.
|
|
66
66
|
|
|
67
|
-
Follow [Build
|
|
67
|
+
Follow [Build plugins with tensoracle's C++ sources](https://sync-dev-org.github.io/tensoracle/cpp-python-repositories/) to locate the sources in the wheel and use the CMake helper in your plugin build.
|
|
68
68
|
|
|
69
69
|
## Convert a PyTorch checkpoint
|
|
70
70
|
|
|
@@ -110,7 +110,7 @@ def graph(network: trt.INetworkDefinition) -> None:
|
|
|
110
110
|
|
|
111
111
|
declaration = EngineBuild(
|
|
112
112
|
inputs={"features": InputShape.ranged((1, 1, 2), (1, 64, 2), (1, 448, 2))},
|
|
113
|
-
settings=BuilderSettings(workspace_limit=
|
|
113
|
+
settings=BuilderSettings(workspace_limit=None, optimization_level=3),
|
|
114
114
|
)
|
|
115
115
|
plan: bytes = build_serialized_engine(graph, declaration)
|
|
116
116
|
```
|
|
@@ -119,6 +119,8 @@ Use `InputShape.fixed((1, 64, 2))` for one input size; the graph may declare tha
|
|
|
119
119
|
|
|
120
120
|
The engine's precision is determined by the tensor types that the graph function places in the network. For an fp16 graph, use `trt.float16` tensors and `np.float16` weights where needed; the graph can also contain fp32 tensors. `EngineBuild` declares input shapes and builder settings. TF32 is always disabled; `BuilderSettings(tf32=True)` raises `ValueError`. The function returns serialized plan bytes. Invalid declarations raise `ValueError`, and a failed TensorRT build raises `RuntimeError`.
|
|
121
121
|
|
|
122
|
+
`BuilderSettings.workspace_limit` defaults to `None`, which leaves the workspace limit at TensorRT's default without calling `set_memory_pool_limit`. To impose a limit, pass a positive integer in bytes, such as `workspace_limit=4 << 30` for 4 GiB. Zero, negative values, booleans, and noninteger values raise `ValueError`.
|
|
123
|
+
|
|
122
124
|
The same API builds bf16, int8, and fp8 graphs. Cast tensors to `trt.bfloat16` for bf16; for int8/fp8, place `add_quantize` / `add_dequantize` layers and load their scales from safetensors. The application determines scales with an external quantization library and chooses output quality limits with `compare_outputs`. fp8 targets sm89 and sm120; bf16 and int8 also target sm86. Follow [Build bf16, int8, and fp8 engines](https://github.com/sync-dev-org/tensoracle/blob/main/docs/precision.md) for a complete example, NumPy dtype constraints, and comparison against an fp32 engine. Use different engine names or graph versions for different precisions.
|
|
123
125
|
|
|
124
126
|
## Save and reopen an engine
|
|
@@ -144,7 +146,9 @@ handle = open_engine(
|
|
|
144
146
|
engine = handle.engine # Keep handle.runtime alive while using the engine.
|
|
145
147
|
```
|
|
146
148
|
|
|
147
|
-
Saved files live in the `tensoracle` directory under `XDG_CACHE_HOME`, or under the home directory's `.cache` when that variable is unset. The same rule applies on every OS; on Windows the home directory is `%USERPROFILE%`, so the default is `%USERPROFILE%\.cache\tensoracle`. The cache identity includes the contents of all declared safetensors weight files and optional `plugins` files, the engine name, graph version, input shapes, builder settings, the GPU's compatibility properties, OS, CPU architecture, and TensorRT version. The GPU is the device of the current CUDA context, or device 0 when no context is current. Its properties are the product name, compute capability, memory bus width, L2 cache size, shared memory limits, texture alignment, multiprocessor count, whether the GPU is integrated, ECC mode, and total memory; another device with the same properties reuses the saved engine. Raise `graph_version` when graph code changes; without a version change, the previous engine is reused. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. Include in `graph_version` any other caller value that changes the engine contents but is not part of the cache identity, such as a plugin manifest or a build recipe. Pass `force_rebuild=True` to replace a cached engine even when it is intact. tensoracle closes a saved engine file after reading it, so another process using an opened engine does not block replacement. On Windows, a process that keeps the saved file itself open prevents replacement or removal with `PermissionError`; after that process closes the file, a file left empty by the failed rebuild is rejected as `CorruptEngineError` and can be rebuilt with `force_rebuild=True`.
|
|
149
|
+
Saved files live in the `tensoracle` directory under `XDG_CACHE_HOME`, or under the home directory's `.cache` when that variable is unset. The same rule applies on every OS; on Windows the home directory is `%USERPROFILE%`, so the default is `%USERPROFILE%\.cache\tensoracle`. The cache identity includes the contents of all declared safetensors weight files and optional `plugins` files, the engine name, graph version, input shapes, the builder's `optimization_level` and `tf32` settings, the GPU's compatibility properties, OS, CPU architecture, and TensorRT version. The GPU is the device of the current CUDA context, or device 0 when no context is current. Its properties are the product name, compute capability, memory bus width, L2 cache size, shared memory limits, texture alignment, multiprocessor count, whether the GPU is integrated, ECC mode, and total memory; another device with the same properties reuses the saved engine. Raise `graph_version` when graph code changes; without a version change, the previous engine is reused. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. Include in `graph_version` any other caller value that changes the engine contents but is not part of the cache identity, such as a plugin manifest or a build recipe. Pass `force_rebuild=True` to replace a cached engine even when it is intact. tensoracle closes a saved engine file after reading it, so another process using an opened engine does not block replacement. On Windows, a process that keeps the saved file itself open prevents replacement or removal with `PermissionError`; after that process closes the file, a file left empty by the failed rebuild is rejected as `CorruptEngineError` and can be rebuilt with `force_rebuild=True`.
|
|
150
|
+
|
|
151
|
+
`workspace_limit` is excluded from the cache identity. Changing it reuses a matching saved engine; pass `force_rebuild=True` to `open_engine` to build again with the new limit. The saved header records the workspace limit used for that build, including `None`, as a reference outside the conditions used for matching. Cache reads leave this reference unchanged. `tensoracle cache list` shows the recorded limit.
|
|
148
152
|
|
|
149
153
|
`plugins` names native TensorRT plugin libraries. Both `open_engine` and `build_serialized_engine` accept it. Each function checks that every library exports `getCreators`, loads it through TensorRT's registry, and retains it for the process before building the graph or deserializing an engine. Repeating the same library does not register it twice. `open_engine` also hashes the loaded library bytes into the engine identity; a changed library selects a different saved engine in a new process. A missing, unreadable, or incompatible library, or a library changed after loading in the same process, raises `PluginLibraryError` before a cached plan is opened. Keep the library and its cubin bundle together in the caller's wheel.
|
|
150
154
|
|
|
@@ -156,6 +160,30 @@ For each weight file, `open_engine` stores its SHA-256 alongside the saved engin
|
|
|
156
160
|
|
|
157
161
|
`CorruptEngineError` reports incomplete or damaged saved files and plans that TensorRT cannot deserialize. When deserialization fails, its message asks the caller to check the required plugin libraries in `plugins=`. `EngineConditionError` reports a saved header with different build conditions. These types and `EngineIOError` derive from `EngineCacheError`. The caller chooses whether to rebuild after an error.
|
|
158
162
|
|
|
163
|
+
## Manage saved engines
|
|
164
|
+
|
|
165
|
+
Inspect saved engines and preview or perform cleanup with the installed command:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
tensoracle cache list
|
|
169
|
+
tensoracle cache prune --unused-for 30 --dry-run
|
|
170
|
+
tensoracle cache prune --unused-for 30
|
|
171
|
+
tensoracle cache prune --max-size 10GiB --dry-run
|
|
172
|
+
tensoracle cache prune --max-size 10GiB
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The commands use the same `XDG_CACHE_HOME` / home `.cache` directory as `open_engine`. They read only filesystem metadata, engine headers, and saved weight digest records. They do not read or checksum the plan body, load the original weights, deserialize engines, import TensorRT, or query a GPU. Listing recognizes the header format; it does not establish that an engine can be loaded.
|
|
176
|
+
|
|
177
|
+
`cache list` prints one JSON object with `directory`, `entries`, and `total_size_bytes`. Each entry contains the file name, size in bytes, recorded time in UTC (`recorded_at`) and exact nanoseconds (`recorded_at_ns`), and the complete header conditions. This distinguishes engines with the same name and graph version but different weights or plugins. Each recognized entry also contains `workspace_limit`: a positive integer in bytes for an explicit build limit, JSON `null` when the build left the limit at TensorRT's default, or `"unknown"` when the header has no reference value. `weight_paths` associates each weight digest with paths from valid, checksum-verified `weight-*.json` records whose SHA-256 matches that digest; an empty `paths` array means unknown. These paths are references and do not establish which application uses an engine or whether the weight file still exists. Empty files have status `building or leftover`; unreadable or invalid headers have status `unrecognized` and a reason.
|
|
178
|
+
|
|
179
|
+
An engine's `.engine` modification time records its initial save or the last successful `open_engine` cache read. Failed loads and these management commands leave that time unchanged. A timestamp write failure, including a read-only cache, does not prevent a successful load, and a disappeared file is never recreated to record its time. The record describes the time of `open_engine`, not whether inference continues afterward. Files saved before timestamp recording was introduced, and files whose timestamp could not be written, may not reflect the actual last successful read.
|
|
180
|
+
|
|
181
|
+
`cache prune` requires exactly one of `--unused-for DAYS` and `--max-size SIZE`. Days are finite nonnegative numbers, may be fractional, and mean 24 hours each; only timestamps strictly earlier than the cutoff are selected. Sizes accept nonnegative bytes or the case-insensitive units `B`, `KiB`, `MiB`, `GiB`, and `TiB` (powers of 1024). Fractions such as `1.5GiB` are allowed and fractional bytes are rounded down. Size pruning selects the oldest recorded times first, breaking ties by file name, until the total `.engine` bytes would fit. Empty and unrecognized files count toward that total but are always excluded from deletion. Weight digest records are kept.
|
|
182
|
+
|
|
183
|
+
Before deletion, pruning prints a JSON `plan` containing the selected engines, excluded files, and a notice that removed engines will be rebuilt the next time they are used. It then prints a JSON `result` separating removed, excluded, failed, and already missing files, the bytes actually removed, and the remaining total. `--dry-run` shows the same targets without changing file contents or recorded times; its result also gives the projected total. Exit status is 0 for success, 1 for filesystem failures, failed deletions, or an unattainable size limit, and 2 for invalid usage. Files that disappear before removal are reported in `missing` and do not count as bytes removed. Observed file changes are reported as failed removals with a reason.
|
|
184
|
+
|
|
185
|
+
Run pruning during maintenance when no engine is being built or opened in the same cache directory. Cleanup provides no lock or guarantee of protection against concurrent builds and reads. Inspect the selection with `--dry-run` before performing cleanup. `tensoracle cache prune --help` describes the options.
|
|
186
|
+
|
|
159
187
|
## Use a saved engine for inference
|
|
160
188
|
|
|
161
189
|
An inference application can call `open_engine` with the same build declaration and files used to save the engine. For example, assume the model package exports `graph`, `declaration`, and `io` matching the example above:
|
|
@@ -336,23 +364,13 @@ Install the producer extra when you need to compile cubins from your own kernels
|
|
|
336
364
|
pip install 'tensoracle[producer]'
|
|
337
365
|
```
|
|
338
366
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
```text
|
|
342
|
-
cpp/
|
|
343
|
-
CMakeLists.txt
|
|
344
|
-
python/
|
|
345
|
-
pyproject.toml
|
|
346
|
-
src/
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
Keep C++ sources in `cpp/`, with a CMake project that builds and runs its tests through CTest without Python. Keep the Python project, its src-layout package, and its uv environment in `python/`; run the project's uv commands from that directory. Tensoracle itself follows this layout, and the installed C++ helper paths described below remain inside its Python package.
|
|
367
|
+
Use the [C++ sources and CMake helper supplied in the tensoracle wheel](https://sync-dev-org.github.io/tensoracle/cpp-python-repositories/) to build your native plugin.
|
|
350
368
|
|
|
351
369
|
`tensoracle.producer.compile_bundle` uses the extra's **Triton 3.8.0** with **ptxas >=13.2,<14** and **cuobjdump** from the PyPI `nvidia-cuda-nvcc` and `nvidia-cuda-cuobjdump` wheels. The extra pins those tools, `nvidia-cuda-crt`, and `nvidia-nvvm` to the 13.2 series. It does not read `CUDA_HOME`; explicit `ptxas` and `cuobjdump` paths override the wheel defaults independently. A missing tool identifies its package and searched path and explains how to install the extra or pass a path. The normal import, engine build, and engine reuse paths do not import the producer or Triton. Cubin production does not need a GPU or import torch; run it without importing torch first. The caller supplies Triton functions and `KernelSpec` records with their public argument types, compile time constants, and any divisibility assumptions. The producer writes sm86, sm89, and sm120 cubins, `bundle.json`, and a C++ translation unit that embeds exactly those cubins. The generated C++ entry records carry each public argument's order, type, count, and divisibility rule into the common launcher. It rejects an unexpected parameter ABI or nonzero scratch requirement. The included [example](https://github.com/sync-dev-org/tensoracle/blob/main/examples/cubin_plugin/README.md#rebuild-the-cubins) has the command to rebuild its cubins from a repository clone.
|
|
352
370
|
|
|
353
371
|
Neither cubin production nor native plugin building requires an OS-installed CUDA Toolkit. For the native build, install PyPI `nvidia-cuda-nvcc==13.2.*` and `nvidia-cuda-runtime==13.2.*`, then pass their `site-packages/nvidia/cu13` directory as `CUDAToolkit_ROOT` (a CMake variable or environment variable). The helper uses its `cuda.h` and links the NVIDIA driver's `libcuda.so` on Linux, including `/usr/lib/wsl/lib/libcuda.so` on WSL, or the wheel's `lib/x64/cuda.lib` on Windows. TensorRT headers still come from the separately prepared SDK. The [SDK guide](https://github.com/sync-dev-org/tensoracle/blob/main/docs/tensorrt-sdk.md#5-pass-the-verified-root-to-the-build-and-tests) gives the setup commands. An explicit OS Toolkit root and the existing default locations remain supported for native builds.
|
|
354
372
|
|
|
355
|
-
The
|
|
373
|
+
The caller implements the graph's meaning, field meanings, weight placement, launch sequence, and variant selection. The common C++ implementation owns typed fields in their original order, handles `IPluginV3` lifecycle methods, checks cubin digests and resources, loads one module per CUDA context, checks the generated argument count and specialization rules, appends the two supported zero scratch pointers, and launches kernels. The caller selects a variant using `Kernel::accepts` and derives the count passed to `Kernel::launch` from its argument array. The common implementation releases modules and device allocations in their owning contexts. The library must export TensorRT's `getCreators`; a static registration constructor is not supported.
|
|
356
374
|
|
|
357
375
|
To record the CUDA inputs used by the plugin build, call `tensoracle_find_cuda` from `TensoracleCuda.cmake` (also included by `TensoracleCubinPlugin.cmake`):
|
|
358
376
|
|
|
@@ -31,7 +31,7 @@ The supported targets are Linux x86_64 (including WSL2) and Windows x86_64, Tens
|
|
|
31
31
|
|
|
32
32
|
Follow the [four-stage optimization workflow](https://github.com/sync-dev-org/tensoracle/blob/main/docs/optimization.md) to establish output quality, evaluate lower precision and plugins, and measure speed.
|
|
33
33
|
|
|
34
|
-
Follow [Build
|
|
34
|
+
Follow [Build plugins with tensoracle's C++ sources](https://sync-dev-org.github.io/tensoracle/cpp-python-repositories/) to locate the sources in the wheel and use the CMake helper in your plugin build.
|
|
35
35
|
|
|
36
36
|
## Convert a PyTorch checkpoint
|
|
37
37
|
|
|
@@ -77,7 +77,7 @@ def graph(network: trt.INetworkDefinition) -> None:
|
|
|
77
77
|
|
|
78
78
|
declaration = EngineBuild(
|
|
79
79
|
inputs={"features": InputShape.ranged((1, 1, 2), (1, 64, 2), (1, 448, 2))},
|
|
80
|
-
settings=BuilderSettings(workspace_limit=
|
|
80
|
+
settings=BuilderSettings(workspace_limit=None, optimization_level=3),
|
|
81
81
|
)
|
|
82
82
|
plan: bytes = build_serialized_engine(graph, declaration)
|
|
83
83
|
```
|
|
@@ -86,6 +86,8 @@ Use `InputShape.fixed((1, 64, 2))` for one input size; the graph may declare tha
|
|
|
86
86
|
|
|
87
87
|
The engine's precision is determined by the tensor types that the graph function places in the network. For an fp16 graph, use `trt.float16` tensors and `np.float16` weights where needed; the graph can also contain fp32 tensors. `EngineBuild` declares input shapes and builder settings. TF32 is always disabled; `BuilderSettings(tf32=True)` raises `ValueError`. The function returns serialized plan bytes. Invalid declarations raise `ValueError`, and a failed TensorRT build raises `RuntimeError`.
|
|
88
88
|
|
|
89
|
+
`BuilderSettings.workspace_limit` defaults to `None`, which leaves the workspace limit at TensorRT's default without calling `set_memory_pool_limit`. To impose a limit, pass a positive integer in bytes, such as `workspace_limit=4 << 30` for 4 GiB. Zero, negative values, booleans, and noninteger values raise `ValueError`.
|
|
90
|
+
|
|
89
91
|
The same API builds bf16, int8, and fp8 graphs. Cast tensors to `trt.bfloat16` for bf16; for int8/fp8, place `add_quantize` / `add_dequantize` layers and load their scales from safetensors. The application determines scales with an external quantization library and chooses output quality limits with `compare_outputs`. fp8 targets sm89 and sm120; bf16 and int8 also target sm86. Follow [Build bf16, int8, and fp8 engines](https://github.com/sync-dev-org/tensoracle/blob/main/docs/precision.md) for a complete example, NumPy dtype constraints, and comparison against an fp32 engine. Use different engine names or graph versions for different precisions.
|
|
90
92
|
|
|
91
93
|
## Save and reopen an engine
|
|
@@ -111,7 +113,9 @@ handle = open_engine(
|
|
|
111
113
|
engine = handle.engine # Keep handle.runtime alive while using the engine.
|
|
112
114
|
```
|
|
113
115
|
|
|
114
|
-
Saved files live in the `tensoracle` directory under `XDG_CACHE_HOME`, or under the home directory's `.cache` when that variable is unset. The same rule applies on every OS; on Windows the home directory is `%USERPROFILE%`, so the default is `%USERPROFILE%\.cache\tensoracle`. The cache identity includes the contents of all declared safetensors weight files and optional `plugins` files, the engine name, graph version, input shapes, builder settings, the GPU's compatibility properties, OS, CPU architecture, and TensorRT version. The GPU is the device of the current CUDA context, or device 0 when no context is current. Its properties are the product name, compute capability, memory bus width, L2 cache size, shared memory limits, texture alignment, multiprocessor count, whether the GPU is integrated, ECC mode, and total memory; another device with the same properties reuses the saved engine. Raise `graph_version` when graph code changes; without a version change, the previous engine is reused. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. Include in `graph_version` any other caller value that changes the engine contents but is not part of the cache identity, such as a plugin manifest or a build recipe. Pass `force_rebuild=True` to replace a cached engine even when it is intact. tensoracle closes a saved engine file after reading it, so another process using an opened engine does not block replacement. On Windows, a process that keeps the saved file itself open prevents replacement or removal with `PermissionError`; after that process closes the file, a file left empty by the failed rebuild is rejected as `CorruptEngineError` and can be rebuilt with `force_rebuild=True`.
|
|
116
|
+
Saved files live in the `tensoracle` directory under `XDG_CACHE_HOME`, or under the home directory's `.cache` when that variable is unset. The same rule applies on every OS; on Windows the home directory is `%USERPROFILE%`, so the default is `%USERPROFILE%\.cache\tensoracle`. The cache identity includes the contents of all declared safetensors weight files and optional `plugins` files, the engine name, graph version, input shapes, the builder's `optimization_level` and `tf32` settings, the GPU's compatibility properties, OS, CPU architecture, and TensorRT version. The GPU is the device of the current CUDA context, or device 0 when no context is current. Its properties are the product name, compute capability, memory bus width, L2 cache size, shared memory limits, texture alignment, multiprocessor count, whether the GPU is integrated, ECC mode, and total memory; another device with the same properties reuses the saved engine. Raise `graph_version` when graph code changes; without a version change, the previous engine is reused. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. Include in `graph_version` any other caller value that changes the engine contents but is not part of the cache identity, such as a plugin manifest or a build recipe. Pass `force_rebuild=True` to replace a cached engine even when it is intact. tensoracle closes a saved engine file after reading it, so another process using an opened engine does not block replacement. On Windows, a process that keeps the saved file itself open prevents replacement or removal with `PermissionError`; after that process closes the file, a file left empty by the failed rebuild is rejected as `CorruptEngineError` and can be rebuilt with `force_rebuild=True`.
|
|
117
|
+
|
|
118
|
+
`workspace_limit` is excluded from the cache identity. Changing it reuses a matching saved engine; pass `force_rebuild=True` to `open_engine` to build again with the new limit. The saved header records the workspace limit used for that build, including `None`, as a reference outside the conditions used for matching. Cache reads leave this reference unchanged. `tensoracle cache list` shows the recorded limit.
|
|
115
119
|
|
|
116
120
|
`plugins` names native TensorRT plugin libraries. Both `open_engine` and `build_serialized_engine` accept it. Each function checks that every library exports `getCreators`, loads it through TensorRT's registry, and retains it for the process before building the graph or deserializing an engine. Repeating the same library does not register it twice. `open_engine` also hashes the loaded library bytes into the engine identity; a changed library selects a different saved engine in a new process. A missing, unreadable, or incompatible library, or a library changed after loading in the same process, raises `PluginLibraryError` before a cached plan is opened. Keep the library and its cubin bundle together in the caller's wheel.
|
|
117
121
|
|
|
@@ -123,6 +127,30 @@ For each weight file, `open_engine` stores its SHA-256 alongside the saved engin
|
|
|
123
127
|
|
|
124
128
|
`CorruptEngineError` reports incomplete or damaged saved files and plans that TensorRT cannot deserialize. When deserialization fails, its message asks the caller to check the required plugin libraries in `plugins=`. `EngineConditionError` reports a saved header with different build conditions. These types and `EngineIOError` derive from `EngineCacheError`. The caller chooses whether to rebuild after an error.
|
|
125
129
|
|
|
130
|
+
## Manage saved engines
|
|
131
|
+
|
|
132
|
+
Inspect saved engines and preview or perform cleanup with the installed command:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
tensoracle cache list
|
|
136
|
+
tensoracle cache prune --unused-for 30 --dry-run
|
|
137
|
+
tensoracle cache prune --unused-for 30
|
|
138
|
+
tensoracle cache prune --max-size 10GiB --dry-run
|
|
139
|
+
tensoracle cache prune --max-size 10GiB
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The commands use the same `XDG_CACHE_HOME` / home `.cache` directory as `open_engine`. They read only filesystem metadata, engine headers, and saved weight digest records. They do not read or checksum the plan body, load the original weights, deserialize engines, import TensorRT, or query a GPU. Listing recognizes the header format; it does not establish that an engine can be loaded.
|
|
143
|
+
|
|
144
|
+
`cache list` prints one JSON object with `directory`, `entries`, and `total_size_bytes`. Each entry contains the file name, size in bytes, recorded time in UTC (`recorded_at`) and exact nanoseconds (`recorded_at_ns`), and the complete header conditions. This distinguishes engines with the same name and graph version but different weights or plugins. Each recognized entry also contains `workspace_limit`: a positive integer in bytes for an explicit build limit, JSON `null` when the build left the limit at TensorRT's default, or `"unknown"` when the header has no reference value. `weight_paths` associates each weight digest with paths from valid, checksum-verified `weight-*.json` records whose SHA-256 matches that digest; an empty `paths` array means unknown. These paths are references and do not establish which application uses an engine or whether the weight file still exists. Empty files have status `building or leftover`; unreadable or invalid headers have status `unrecognized` and a reason.
|
|
145
|
+
|
|
146
|
+
An engine's `.engine` modification time records its initial save or the last successful `open_engine` cache read. Failed loads and these management commands leave that time unchanged. A timestamp write failure, including a read-only cache, does not prevent a successful load, and a disappeared file is never recreated to record its time. The record describes the time of `open_engine`, not whether inference continues afterward. Files saved before timestamp recording was introduced, and files whose timestamp could not be written, may not reflect the actual last successful read.
|
|
147
|
+
|
|
148
|
+
`cache prune` requires exactly one of `--unused-for DAYS` and `--max-size SIZE`. Days are finite nonnegative numbers, may be fractional, and mean 24 hours each; only timestamps strictly earlier than the cutoff are selected. Sizes accept nonnegative bytes or the case-insensitive units `B`, `KiB`, `MiB`, `GiB`, and `TiB` (powers of 1024). Fractions such as `1.5GiB` are allowed and fractional bytes are rounded down. Size pruning selects the oldest recorded times first, breaking ties by file name, until the total `.engine` bytes would fit. Empty and unrecognized files count toward that total but are always excluded from deletion. Weight digest records are kept.
|
|
149
|
+
|
|
150
|
+
Before deletion, pruning prints a JSON `plan` containing the selected engines, excluded files, and a notice that removed engines will be rebuilt the next time they are used. It then prints a JSON `result` separating removed, excluded, failed, and already missing files, the bytes actually removed, and the remaining total. `--dry-run` shows the same targets without changing file contents or recorded times; its result also gives the projected total. Exit status is 0 for success, 1 for filesystem failures, failed deletions, or an unattainable size limit, and 2 for invalid usage. Files that disappear before removal are reported in `missing` and do not count as bytes removed. Observed file changes are reported as failed removals with a reason.
|
|
151
|
+
|
|
152
|
+
Run pruning during maintenance when no engine is being built or opened in the same cache directory. Cleanup provides no lock or guarantee of protection against concurrent builds and reads. Inspect the selection with `--dry-run` before performing cleanup. `tensoracle cache prune --help` describes the options.
|
|
153
|
+
|
|
126
154
|
## Use a saved engine for inference
|
|
127
155
|
|
|
128
156
|
An inference application can call `open_engine` with the same build declaration and files used to save the engine. For example, assume the model package exports `graph`, `declaration`, and `io` matching the example above:
|
|
@@ -303,23 +331,13 @@ Install the producer extra when you need to compile cubins from your own kernels
|
|
|
303
331
|
pip install 'tensoracle[producer]'
|
|
304
332
|
```
|
|
305
333
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
```text
|
|
309
|
-
cpp/
|
|
310
|
-
CMakeLists.txt
|
|
311
|
-
python/
|
|
312
|
-
pyproject.toml
|
|
313
|
-
src/
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
Keep C++ sources in `cpp/`, with a CMake project that builds and runs its tests through CTest without Python. Keep the Python project, its src-layout package, and its uv environment in `python/`; run the project's uv commands from that directory. Tensoracle itself follows this layout, and the installed C++ helper paths described below remain inside its Python package.
|
|
334
|
+
Use the [C++ sources and CMake helper supplied in the tensoracle wheel](https://sync-dev-org.github.io/tensoracle/cpp-python-repositories/) to build your native plugin.
|
|
317
335
|
|
|
318
336
|
`tensoracle.producer.compile_bundle` uses the extra's **Triton 3.8.0** with **ptxas >=13.2,<14** and **cuobjdump** from the PyPI `nvidia-cuda-nvcc` and `nvidia-cuda-cuobjdump` wheels. The extra pins those tools, `nvidia-cuda-crt`, and `nvidia-nvvm` to the 13.2 series. It does not read `CUDA_HOME`; explicit `ptxas` and `cuobjdump` paths override the wheel defaults independently. A missing tool identifies its package and searched path and explains how to install the extra or pass a path. The normal import, engine build, and engine reuse paths do not import the producer or Triton. Cubin production does not need a GPU or import torch; run it without importing torch first. The caller supplies Triton functions and `KernelSpec` records with their public argument types, compile time constants, and any divisibility assumptions. The producer writes sm86, sm89, and sm120 cubins, `bundle.json`, and a C++ translation unit that embeds exactly those cubins. The generated C++ entry records carry each public argument's order, type, count, and divisibility rule into the common launcher. It rejects an unexpected parameter ABI or nonzero scratch requirement. The included [example](https://github.com/sync-dev-org/tensoracle/blob/main/examples/cubin_plugin/README.md#rebuild-the-cubins) has the command to rebuild its cubins from a repository clone.
|
|
319
337
|
|
|
320
338
|
Neither cubin production nor native plugin building requires an OS-installed CUDA Toolkit. For the native build, install PyPI `nvidia-cuda-nvcc==13.2.*` and `nvidia-cuda-runtime==13.2.*`, then pass their `site-packages/nvidia/cu13` directory as `CUDAToolkit_ROOT` (a CMake variable or environment variable). The helper uses its `cuda.h` and links the NVIDIA driver's `libcuda.so` on Linux, including `/usr/lib/wsl/lib/libcuda.so` on WSL, or the wheel's `lib/x64/cuda.lib` on Windows. TensorRT headers still come from the separately prepared SDK. The [SDK guide](https://github.com/sync-dev-org/tensoracle/blob/main/docs/tensorrt-sdk.md#5-pass-the-verified-root-to-the-build-and-tests) gives the setup commands. An explicit OS Toolkit root and the existing default locations remain supported for native builds.
|
|
321
339
|
|
|
322
|
-
The
|
|
340
|
+
The caller implements the graph's meaning, field meanings, weight placement, launch sequence, and variant selection. The common C++ implementation owns typed fields in their original order, handles `IPluginV3` lifecycle methods, checks cubin digests and resources, loads one module per CUDA context, checks the generated argument count and specialization rules, appends the two supported zero scratch pointers, and launches kernels. The caller selects a variant using `Kernel::accepts` and derives the count passed to `Kernel::launch` from its argument array. The common implementation releases modules and device allocations in their owning contexts. The library must export TensorRT's `getCreators`; a static registration constructor is not supported.
|
|
323
341
|
|
|
324
342
|
To record the CUDA inputs used by the plugin build, call `tensoracle_find_cuda` from `TensoracleCuda.cmake` (also included by `TensoracleCubinPlugin.cmake`):
|
|
325
343
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Build plugins with tensoracle's C++ sources
|
|
2
|
+
|
|
3
|
+
Tensoracle supplies the shared C++ implementation and CMake helpers for cubin plugins. Your model package supplies the kernels and model-specific plugin behavior, compiles the native plugin, and packages it for the application.
|
|
4
|
+
|
|
5
|
+
## C++ sources in the wheel
|
|
6
|
+
|
|
7
|
+
The tensoracle wheel includes:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
tensoracle/cpp/
|
|
11
|
+
include/tensoracle/cubin_plugin.hpp
|
|
12
|
+
src/cubin_plugin.cpp
|
|
13
|
+
cmake/TensoracleCubinPlugin.cmake
|
|
14
|
+
cmake/TensoracleCuda.cmake
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The wheel contains no native binaries and uses the `py3-none-any` tag. Your plugin's native library is compiled separately and belongs to your model package.
|
|
18
|
+
|
|
19
|
+
## Prepare the build inputs
|
|
20
|
+
|
|
21
|
+
Use CMake 3.20 or later and a C++17 compiler. Follow [Prepare a TensorRT SDK](tensorrt-sdk.md) to obtain and verify the TensorRT 11 headers and library and prepare the PyPI CUDA headers and driver link library. That guide covers Linux, WSL2, and [Windows](tensorrt-sdk.md#windows-x86_64); no OS-installed CUDA Toolkit is required.
|
|
22
|
+
|
|
23
|
+
Generate a cubin bundle with the [cubin producer](api/producer.md). The bundle directory must contain `bundle.cpp`, `bundle.json`, and the cubin files. Cubin production runs on Linux; the same bundle can be used to build a Windows plugin DLL. Follow [Build a cubin plugin](index.md#build-a-cubin-plugin) for the model-specific plugin interface and tensor declarations.
|
|
24
|
+
|
|
25
|
+
## Use the packaged CMake helper
|
|
26
|
+
|
|
27
|
+
In the Python environment where tensoracle is installed, locate its C++ source directory:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python -c 'from importlib.metadata import distribution; print(distribution("tensoracle").locate_file("tensoracle/cpp"))'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Pass that directory as `TENSORACLE_CPP_ROOT` to your plugin's CMake project. Include the helper and give it your plugin source, verified SDK root, and generated bundle directory:
|
|
34
|
+
|
|
35
|
+
```cmake
|
|
36
|
+
cmake_minimum_required(VERSION 3.20)
|
|
37
|
+
project(my_model_plugin LANGUAGES CXX)
|
|
38
|
+
|
|
39
|
+
include("${TENSORACLE_CPP_ROOT}/cmake/TensoracleCubinPlugin.cmake")
|
|
40
|
+
tensoracle_add_cubin_plugin(
|
|
41
|
+
TARGET my_model_plugin
|
|
42
|
+
TENSORRT_ROOT "${TENSORRT_ROOT}"
|
|
43
|
+
BUNDLE_ROOT "${TENSORACLE_BUNDLE_ROOT}"
|
|
44
|
+
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`tensoracle_add_cubin_plugin` builds a shared library from your `plugin.cpp`, tensoracle's common `cubin_plugin.cpp`, and the bundle's generated `bundle.cpp`. It adds the required include directories and links TensorRT and the CUDA driver.
|
|
48
|
+
|
|
49
|
+
For a Bash build, replace the absolute paths below with your plugin project, installed tensoracle sources, verified SDK, PyPI CUDA root, and generated bundle:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cmake -S /absolute/path/to/plugin-project -B build/plugin \
|
|
53
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
54
|
+
-DTENSORACLE_CPP_ROOT=/absolute/path/to/tensoracle/cpp \
|
|
55
|
+
-DTENSORRT_ROOT=/absolute/path/to/TensorRT-SDK \
|
|
56
|
+
-DCUDAToolkit_ROOT=/absolute/path/to/site-packages/nvidia/cu13 \
|
|
57
|
+
-DTENSORACLE_BUNDLE_ROOT=/absolute/path/to/bundle
|
|
58
|
+
cmake --build build/plugin --config Release
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The [plugin guide](https://github.com/sync-dev-org/tensoracle#build-a-cubin-plugin) documents the required `getCreators` export and the optional `tensoracle_find_cuda` function and `tensoracle_cuda_driver` target for consumers that also need the resolved CUDA inputs.
|
|
62
|
+
|
|
63
|
+
## Package and inspect the plugin
|
|
64
|
+
|
|
65
|
+
Follow the [cubin plugin example](https://github.com/sync-dev-org/tensoracle/blob/main/examples/cubin_plugin/README.md#build-and-inspect-the-wheel) for packaging the native library and bundle in your model wheel and testing it in a runtime environment. Use the [bundle inspection API](api/bundle.md) to check the bundle and its match with the compiled plugin before distribution.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Follow the [four-stage optimization workflow](optimization.md) to establish output quality, evaluate lower precision and plugins, and measure speed.
|
|
6
6
|
|
|
7
|
-
Follow [Build
|
|
7
|
+
Follow [Build plugins with tensoracle's C++ sources](cpp-python-repositories.md) to locate the sources in the wheel and use the CMake helper in your plugin build.
|
|
8
8
|
|
|
9
9
|
## Terms
|
|
10
10
|
|
|
@@ -74,6 +74,32 @@ handle = open_engine(
|
|
|
74
74
|
|
|
75
75
|
`my_model` represents the application's model package. On a valid cache hit, `open_engine` does not call `graph`; on a miss, it builds and saves a new engine. Raise `graph_version` when the graph code changes or when any other caller value that changes the engine contents but is not part of the cache identity changes, such as a plugin manifest or a build recipe. `open_engine` itself does not execute the engine or manage GPU buffers. Create an execution unit from its returned handle to enqueue inference. Saved engines live under `XDG_CACHE_HOME/tensoracle`, or `~/.cache/tensoracle` when `XDG_CACHE_HOME` is unset. On Windows, `~` is `%USERPROFILE%`. See the [complete cache example](https://github.com/sync-dev-org/tensoracle#save-and-reopen-an-engine) for the declaration and expected input and output types.
|
|
76
76
|
|
|
77
|
+
`workspace_limit` is excluded from the cache identity; `optimization_level` and `tf32` remain in the conditions. Changing only the workspace limit reuses a matching saved engine. Pass `force_rebuild=True` to `open_engine` to build again with the new limit. The saved header records the workspace limit used for that build, including `None`, as a reference outside the conditions used for matching. Cache reads leave this reference unchanged. `tensoracle cache list` shows the recorded limit.
|
|
78
|
+
|
|
79
|
+
### Manage saved engines
|
|
80
|
+
|
|
81
|
+
Inspect saved engines and preview or perform cleanup with the installed command:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
tensoracle cache list
|
|
85
|
+
tensoracle cache prune --unused-for 30 --dry-run
|
|
86
|
+
tensoracle cache prune --unused-for 30
|
|
87
|
+
tensoracle cache prune --max-size 10GiB --dry-run
|
|
88
|
+
tensoracle cache prune --max-size 10GiB
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The commands use the same `XDG_CACHE_HOME` / home `.cache` directory as `open_engine`. They read only filesystem metadata, engine headers, and saved weight digest records. They do not read or checksum the plan body, load the original weights, deserialize engines, import TensorRT, or query a GPU. Listing recognizes the header format; it does not establish that an engine can be loaded.
|
|
92
|
+
|
|
93
|
+
`cache list` prints one JSON object with `directory`, `entries`, and `total_size_bytes`. Each entry contains the file name, size in bytes, recorded time in UTC (`recorded_at`) and exact nanoseconds (`recorded_at_ns`), and the complete header conditions. This distinguishes engines with the same name and graph version but different weights or plugins. Each recognized entry also contains `workspace_limit`: a positive integer in bytes for an explicit build limit, JSON `null` when the build left the limit at TensorRT's default, or `"unknown"` when the header has no reference value. `weight_paths` associates each weight digest with paths from valid, checksum-verified `weight-*.json` records whose SHA-256 matches that digest; an empty `paths` array means unknown. These paths are references and do not establish which application uses an engine or whether the weight file still exists. Empty files have status `building or leftover`; unreadable or invalid headers have status `unrecognized` and a reason.
|
|
94
|
+
|
|
95
|
+
An engine's `.engine` modification time records its initial save or the last successful `open_engine` cache read. Failed loads and these management commands leave that time unchanged. A timestamp write failure, including a read-only cache, does not prevent a successful load, and a disappeared file is never recreated to record its time. The record describes the time of `open_engine`, not whether inference continues afterward. Files saved before timestamp recording was introduced, and files whose timestamp could not be written, may not reflect the actual last successful read.
|
|
96
|
+
|
|
97
|
+
`cache prune` requires exactly one of `--unused-for DAYS` and `--max-size SIZE`. Days are finite nonnegative numbers, may be fractional, and mean 24 hours each; only timestamps strictly earlier than the cutoff are selected. Sizes accept nonnegative bytes or the case-insensitive units `B`, `KiB`, `MiB`, `GiB`, and `TiB` (powers of 1024). Fractions such as `1.5GiB` are allowed and fractional bytes are rounded down. Size pruning selects the oldest recorded times first, breaking ties by file name, until the total `.engine` bytes would fit. Empty and unrecognized files count toward that total but are always excluded from deletion. Weight digest records are kept.
|
|
98
|
+
|
|
99
|
+
Before deletion, pruning prints a JSON `plan` containing the selected engines, excluded files, and a notice that removed engines will be rebuilt the next time they are used. It then prints a JSON `result` separating removed, excluded, failed, and already missing files, the bytes actually removed, and the remaining total. `--dry-run` shows the same targets without changing file contents or recorded times; its result also gives the projected total. Exit status is 0 for success, 1 for filesystem failures, failed deletions, or an unattainable size limit, and 2 for invalid usage. Files that disappear before removal are reported in `missing` and do not count as bytes removed. Observed file changes are reported as failed removals with a reason.
|
|
100
|
+
|
|
101
|
+
Run pruning during maintenance when no engine is being built or opened in the same cache directory. Cleanup provides no lock or guarantee of protection against concurrent builds and reads. Inspect the selection with `--dry-run` before performing cleanup. `tensoracle cache prune --help` describes the options.
|
|
102
|
+
|
|
77
103
|
### Execute an engine
|
|
78
104
|
|
|
79
105
|
The execution flow is: open the engine, create an execution unit, set all ranged input shapes together, read concrete output shapes and dtypes, allocate output buffers, then enqueue the device addresses on a caller-owned stream. Each `EngineExecution` keeps the handle alive and owns an independent TensorRT context. Fixed inputs and single-point profiles are initialized when the unit is created. Ranged inputs retain their shapes until the next successful `set_input_shapes` call. A partial TensorRT setting failure blocks queries for concrete shapes and enqueue until a complete setting succeeds.
|
|
@@ -228,13 +254,13 @@ Engines with loops or conditionals, or layers or plugins that synchronize with t
|
|
|
228
254
|
|
|
229
255
|
### Build a standard graph
|
|
230
256
|
|
|
231
|
-
Define `graph(network)` with TensorRT's Python network API and load model weights from safetensors. Describe each graph input with `InputShape.fixed` or `InputShape.ranged`, and pass an `EngineBuild` declaration to `build_serialized_engine`. `EngineBuild` declares input shapes and builder settings; the graph function determines precision through the tensor types it places in the network. The supported precisions are fp32 (with TF32 disabled), fp16, bf16, int8, and fp8. The [bf16, int8, and fp8 guide](precision.md) shows tensor casts, explicit Q/DQ layers, and scales supplied through safetensors; fp8 targets sm89 and sm120. `open_engine` uses the same declaration plus a name, graph version, weight files, and `EngineIO` to save and reuse a checked engine. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. The [graph example](https://github.com/sync-dev-org/tensoracle#define-and-build-a-standard-graph) shows the exact calls.
|
|
257
|
+
Define `graph(network)` with TensorRT's Python network API and load model weights from safetensors. Describe each graph input with `InputShape.fixed` or `InputShape.ranged`, and pass an `EngineBuild` declaration to `build_serialized_engine`. `EngineBuild` declares input shapes and builder settings; the graph function determines precision through the tensor types it places in the network. `BuilderSettings.workspace_limit` defaults to `None`, leaving the workspace limit at TensorRT's default. To impose a limit, pass a positive integer in bytes, such as `workspace_limit=4 << 30` for 4 GiB. Zero, negative values, booleans, and noninteger values raise `ValueError`. The supported precisions are fp32 (with TF32 disabled), fp16, bf16, int8, and fp8. The [bf16, int8, and fp8 guide](precision.md) shows tensor casts, explicit Q/DQ layers, and scales supplied through safetensors; fp8 targets sm89 and sm120. `open_engine` uses the same declaration plus a name, graph version, weight files, and `EngineIO` to save and reuse a checked engine. Use a different `name` or `graph_version` for engines with different tensor types, such as fp32 and fp16. The [graph example](https://github.com/sync-dev-org/tensoracle#define-and-build-a-standard-graph) shows the exact calls.
|
|
232
258
|
|
|
233
259
|
The application runs the engine and passes a CPU NumPy candidate output and a corresponding reference output to `compare_outputs`. The application chooses the acceptance limits. See [Compare output arrays](https://github.com/sync-dev-org/tensoracle#compare-output-arrays).
|
|
234
260
|
|
|
235
261
|
### Build a cubin plugin
|
|
236
262
|
|
|
237
|
-
|
|
263
|
+
Use the [C++ sources and CMake helper supplied in the tensoracle wheel](cpp-python-repositories.md) to build your native plugin.
|
|
238
264
|
|
|
239
265
|
Install `tensoracle[producer]` when you need to compile cubins from your own kernels:
|
|
240
266
|
|
|
@@ -35,7 +35,7 @@ nav:
|
|
|
35
35
|
- Optimization workflow: optimization.md
|
|
36
36
|
- bf16, int8, and fp8 engines: precision.md
|
|
37
37
|
- TensorRT SDK setup: tensorrt-sdk.md
|
|
38
|
-
- C++
|
|
38
|
+
- C++ plugin builds: cpp-python-repositories.md
|
|
39
39
|
- API reference:
|
|
40
40
|
- Engine and comparison: api/index.md
|
|
41
41
|
- Cubin bundle inspection: api/bundle.md
|
|
@@ -24,6 +24,9 @@ dependencies = [
|
|
|
24
24
|
"tensorrt-cu13>=11.0,<12",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
|
+
[project.scripts]
|
|
28
|
+
tensoracle = "tensoracle._cli:main"
|
|
29
|
+
|
|
27
30
|
[project.urls]
|
|
28
31
|
documentation = "https://sync-dev-org.github.io/tensoracle/"
|
|
29
32
|
repository = "https://github.com/sync-dev-org/tensoracle"
|
|
@@ -63,6 +66,7 @@ exclude = [
|
|
|
63
66
|
"/.github/",
|
|
64
67
|
"/AGENTS.md",
|
|
65
68
|
"/CLAUDE.md",
|
|
69
|
+
"/intro/",
|
|
66
70
|
"/tools/",
|
|
67
71
|
"/noren.yaml",
|
|
68
72
|
"/noren-words.txt",
|
|
@@ -69,10 +69,16 @@ class InputShape:
|
|
|
69
69
|
class BuilderSettings:
|
|
70
70
|
"""TensorRT builder options that affect the serialized engine."""
|
|
71
71
|
|
|
72
|
-
workspace_limit: int
|
|
72
|
+
workspace_limit: int | None = None
|
|
73
73
|
optimization_level: int = 3
|
|
74
74
|
tf32: bool = False
|
|
75
75
|
|
|
76
|
+
def __post_init__(self) -> None:
|
|
77
|
+
if self.workspace_limit is not None and (
|
|
78
|
+
type(self.workspace_limit) is not int or self.workspace_limit <= 0
|
|
79
|
+
):
|
|
80
|
+
raise ValueError("workspace_limit must be a positive integer or None")
|
|
81
|
+
|
|
76
82
|
|
|
77
83
|
@dataclass(frozen=True)
|
|
78
84
|
class EngineBuild:
|
|
@@ -103,8 +109,6 @@ def _build_serialized_engine(
|
|
|
103
109
|
) -> tuple[bytes, tuple[str, ...]]:
|
|
104
110
|
if declaration.settings.tf32:
|
|
105
111
|
raise ValueError("TF32 cannot be enabled")
|
|
106
|
-
if declaration.settings.workspace_limit <= 0:
|
|
107
|
-
raise ValueError("workspace_limit must be positive")
|
|
108
112
|
if not 0 <= declaration.settings.optimization_level <= 5:
|
|
109
113
|
raise ValueError("optimization_level must be between 0 and 5")
|
|
110
114
|
|
|
@@ -125,9 +129,10 @@ def _build_serialized_engine(
|
|
|
125
129
|
_warn_shape_tensor_outputs(output_names, stacklevel=3)
|
|
126
130
|
config = builder.create_builder_config()
|
|
127
131
|
config.clear_flag(trt.BuilderFlag.TF32)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
if declaration.settings.workspace_limit is not None:
|
|
133
|
+
config.set_memory_pool_limit(
|
|
134
|
+
trt.MemoryPoolType.WORKSPACE, declaration.settings.workspace_limit
|
|
135
|
+
)
|
|
131
136
|
config.builder_optimization_level = declaration.settings.optimization_level
|
|
132
137
|
|
|
133
138
|
inputs = {
|