Inference
- What
InferenceOpdoes and which inference backend it uses - How to describe one or more models with
InferenceOpParams, in C++ or YAML - How the operator picks a dispatch path and when it falls back to a slower one
- How to build the module and link it from an installed SDK
Holoscan Inference is the core module that provides holoscan::ops::InferenceOp,
an inference operator backed with TensorRT for Holoscan pipelines. Give it one or more
model files and the input and output tensor names each model consumes and
produces; the operator builds (or loads a cached) TensorRT engine per model,
declares one Holoscan port per configured tensor, and runs inference on the
fastest dispatch strategy that is safe for your configuration. The backend
library is HoloInfer, which owns the per-model TensorRT contexts and the
multi-model dispatch manager.
InferenceOp and InferenceOpParams, declared in
<holoscan/operators/inference/inference.hpp>, are the public, supported API
of this module in Holoscan SDK 5.0. The HoloInfer library beneath the operator
is internal: the holoinfer libraries and utility headers that install with
the module carry no source or ABI compatibility promise, and they may change
in any release. Write applications against the operator.
The operator
InferenceOp is constructed from an InferenceOpParams aggregate declared in
<holoscan/operators/inference/inference.hpp>. Three fields are required:
Every tensor named in input_map becomes an input port and every tensor in
output_map becomes an output port, so upstream and downstream operators
connect to inference by tensor name. The remaining fields tune the backend and
the dispatch path:
The first time HoloInfer sees an .onnx source it builds a TensorRT engine and
caches it next to the model. The cache filename encodes the GPU, compute
capability, TensorRT version, precision, DLA core, and a hash of every other
build-affecting option, so a stale engine is never reused after a
configuration change.
Configure from YAML
InferenceOpParams has two loaders that share one schema, keyed 1:1 on the
field names above:
InferenceOpParams::from_yaml(path)reads the file’s root as one operator’s parameters — the convention used by every example config.InferenceOpParams::from_yaml_node(node, config_dir)reads an already parsed node, so one YAML file can configure several operators under distinct keys. Relative model paths resolve againstconfig_dir.
The allocator field cannot be populated from YAML; assign it in code after
loading when a non-default allocator is required. Both loaders report a
missing required key with std::runtime_error.
Dispatch selection
At start() the operator inspects its configuration and selects one of seven
dispatch kinds. There is no user-facing opt-in; the fast paths apply
automatically when every model uses the trt backend, inputs are
device-resident, and no model’s output feeds another model’s input:
When a configuration is unsafe for the requested path, the operator degrades
one rung at a time and logs a fallback triggered — <REASON> warning that
names the requested and selected paths and suggests a fix. Configuration-time
rungs include a stream pool smaller than the model count (demote to
sequential), chained models or host inputs (use kStandard), and
dynamic-shape parallel dispatch with CUDA Graphs but no green-context pool
(serialize). One runtime rung swaps a blocking-mode pool stream for a
non-blocking one when CUDA Graphs require it.
For the best concurrent throughput with several static-shape models, supply a
cuda_stream_pool with at least one stream per model and a
cuda_green_context_pool with one partition per model. Without a green-context
pool the operator still runs models in parallel but serializes CUDA Graph
capture behind a process-wide mutex during the first few ticks.
Example
The module ships modules/inference/examples with eight YAML configurations that
progress from a single model to concurrent dynamic-shape models with CUDA
Graphs and context isolation:
See modules/inference/examples
for the per-scenario walkthrough.
Build, test, and consume
HOLOSCAN_BUILD_INFERENCE defaults to ON. InferenceOp requires CUDA and
TensorRT 10.3 or newer at runtime; see the
installation footnotes for
platform coverage. To run PyTorch models next to the pipeline, install
PyTorch as described in
Installing PyTorch. Build and test through the SDK-level runner:
For installed consumers, use the main Holoscan package to load Inference as a component and link the operator and backend targets:
Alternatively, load the dedicated Inference package and link its aggregate target:
Replace the example path with the SDK’s shared package directory. The standalone
package config is installed under lib/cmake/holoscan, so a bare
find_package(holoscan-inference) may not find it through the usual
package-name search. You can instead set holoscan-inference_DIR to
<prefix>/lib/cmake/holoscan (for example, with
-Dholoscan-inference_DIR=<prefix>/lib/cmake/holoscan).
Recap
InferenceOpis a TensorRT-only inference operator; models, ports, and options are described byInferenceOpParams, in C++ or YAML.- TensorRT engines are built once from ONNX and cached with a configuration-aware filename.
- The operator picks the fastest safe dispatch kind at
start()and logs a named fallback whenever it must degrade. - Build with
HOLOSCAN_BUILD_INFERENCE; consume withfind_package(holoscan COMPONENTS inference), or use the dedicatedfind_package(holoscan-inference)package with its package-directory hint. - Next: Vision.