Jump to content

Complete Operator Patterns

From RidgeRun Developer Wiki

🚧 Documentation is under development

The Holoscan SDK guide is currently under active development. Some sections may be incomplete or change without notice.

Questions? Contact RidgeRun or email to support@ridgerun.com.

Contents Pin





Complete Operator Patterns

Once the operator flow is familiar, start from the complete example that matches the data your application needs to move. Each pattern connects the operator declarations, graph, compilation, run control, result checks, and shutdown in one program. Adapt the smallest matching pattern, then return to the focused guides when a design choice needs more explanation.


Prerequisites
Follow Application, Graph, and Operator Anatomy for the application flow, Writing a Minimal Operator for the first scalar graph, and Writing Tensor Operators before adapting a Tensor example. The shared build path is Build the SDK on AGX Orin.


Choose a complete pattern

Use the application outcome to choose a starting point:

Application need Start with What it demonstrates
A small scalar pipeline Writing a Minimal Operator or First Pipeline Operator declarations, graph wiring, compilation, and run control.
A host Tensor produced and inspected in one process Tensors 101 Runtime-owned host storage, checked writes, publication, and bounded inspection.
A device Tensor with a separate inspection branch Tensors in Depth CUDA-stream writes, device processing, explicit host readback, and resource cleanup.
Structured sensor measurements Schema Payloads Generated schema payloads, sensor metadata, validation, and bounded completion.
An existing Tensor should pass through unchanged Forward an existing Tensor sample A pass-through output and sample-preserving publication.
A fixed binary control contract is required Raw POD payloads Explicit identity and byte-layout compatibility for a narrow integration boundary.

The official Your First Operator in the NVIDIA Holoscan SDK documentation is the shortest external introduction. For Tensor applications, continue with Tensors 101 in the NVIDIA Holoscan SDK documentation.

Follow the complete application flow

All of the patterns follow the same user-visible sequence:

Stage Application decision Continue with
Describe Declare operators, typed ports, parameters, and Tensor or schema contracts. Reading and Writing Values and Samples
Connect Build the graph and choose the input that drives each activation. Building Graphs and Queue Policies
Compile Check that the authored graph and resource bounds form an accepted plan. Automatic Partitioning and Plan Inspection
Run Choose blocking or asynchronous control, then observe results and shutdown. Running and Stopping
Adapt Change the payload path, ownership, or preparation boundary to match the application. Allocation Ownership and Tensor Pools

The complete source files below are the runnable reference for each path. The snippets on this page point to the decision being demonstrated; they are not replacements for the full program.

Start with a host Tensor round trip

Tensors 101 is a compact host-Tensor application. A periodic producer creates a fixed float32 array, a downstream inspector receives it, and the application checks the observations before shutting down. It is a useful first Tensor pattern when the application needs runtime-owned storage and CPU access.

The producer declares a host output with finite capacity and writes each result before publishing it. The inspector checks the received representation, readiness, byte count, and values before releasing its read claim. The main() connects the graph, compiles it, runs it asynchronously, and verifies observations, termination, and diagnostics.

Use Writing Tensor Operators when the producer must transform the Tensor, and Allocation Ownership and Tensor Pools when retained samples or pool capacity affect the design.

Add device storage and an inspection branch

Tensors in Depth is the next step when processing belongs on a CUDA device. Its source writes device storage on the runtime stream, sends the result to a device consumer, and adds a separate inspection branch that copies selected data to host memory.

The source checks the assigned stream and every allocation, write, commit, and publication result. The device consumer receives ready data and performs a device-to-device copy for its work. The inspection sink owns the private readback resources until the copy completes.

Use Zero-Copy Data Flow and CUDA Stream Ordering for readiness and private-stream obligations. A shared Tensor handle preserves the backing identity; the example's device computation and host inspection still make their own explicit data movements.

Carry structured sensor measurements

Schema Payloads shows three independent schema lanes, including an IMU measurement path. The IMU producer fills a generated value with frame, timestamp, sequence, and measurement fields. The IMU sink checks the received value and its nested metadata before interpreting it. The main() compiles the lanes, waits for bounded completion, and checks the expected observations.

Use Sensor Payloads and Schemas to choose the sensor payload shape. That page introduces image and IMU schema types, acquisition metadata, and the relationship between a schema value and its Tensor fields.

Build and run a complete program

Each example directory includes an installed-consumer CMake file. Choose one pattern, copy its source and CMake file into an application workspace, then configure and build it with the SDK installation that your application uses:

sdk_source=/path/to/holoscan-sdk
sdk_install=/opt/nvidia/holoscan
example=tensors_101
workspace="$PWD/operator-patterns/$example"

mkdir -p "$workspace"
cp "$sdk_source/examples/$example/cpp/$example.cpp" "$workspace/"
cp "$sdk_source/examples/$example/cpp/CMakeLists.min.txt" "$workspace/CMakeLists.txt"
cmake -S "$workspace" -B "$workspace/build" \
  -DCMAKE_PREFIX_PATH="$sdk_install"
cmake --build "$workspace/build"
ctest --test-dir "$workspace/build" --output-on-failure

Use tensors_101 for a host-only application path. Select tensors_in_depth when a usable CUDA device is available, and select schema_payloads when the application needs generated sensor values. The example source and the installed SDK must come from the same SDK build family.

Forward an existing Tensor sample

Use a pass-through output when the next operator should receive the existing Tensor and its sample metadata. The output declares TensorOutputStorage::kPassThrough so the graph validates a compatible representation without requesting new backing.

With compatible Input<Tensor> and Output<Tensor> ports, the compute method can forward the owning sample:

holoscan::expected<void, holoscan::Error> compute(
    holoscan::ExecutionContext&) override {
  auto sample = input.receive();
  if (!sample) {
    return holoscan::make_unexpected(std::move(sample).error());
  }
  return output.emit(std::move(*sample));
}

The sample overload of emit() preserves the sample's capture, source clock, trace, frame identity, and semantic flags. Forwarding does not authorize the operator to modify the received Tensor. See Reading and Writing Values and Samples for the read and publication choices.

Use a raw POD only when its contract is appropriate

An application-defined C++ struct does not become a port payload just because it is copyable. A generated schema is the usual choice for structured sensor messages. The raw-POD path fits a narrow, coordinated binary contract where the producer and consumer control the identity and layout together.

The declaration requires ChannelTypeIdentity<T> and ChannelPodLayout<T> specializations. The layout validator checks identity and byte coverage. Pointer members, implicit padding, and a size-only identity do not form a portable contract.

Use the Experimental POD Payloads example for the complete producer and consumer. Keep this path separate from the Tensor and generated-schema paths so the receiving application knows exactly which binary layout it accepts.


Related examples and concepts

Examples

Concepts

Source


Cookies help us deliver our services. By using our services, you agree to our use of cookies.