Implementation:NVIDIA DALI C API V2 Pipeline Outputs
| Knowledge Sources | |
|---|---|
| Domains | Data_Pipeline, C_API |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
The pipeline outputs module implements the C API v2 functions for accessing DALI pipeline output tensor lists and operator traces through an independent output handle.
Description
This file implements the PipelineOutputs class and its associated C API functions within the dali::c_api namespace. The class encapsulates a DALI Workspace that holds the results of a pipeline execution, separating output lifetime from the pipeline handle itself. This design allows outputs to be retained and processed even after the pipeline starts computing the next iteration.
The PipelineOutputs constructor receives a raw Pipeline pointer and an AccessOrder, calls ShareOutputs to populate the workspace, and stores the pipeline as the producer for cleanup. The destructor calls ReleaseOutputs on the producer pipeline, enabling the pipeline to reuse output buffers. The Get(int index) method lazily wraps workspace outputs as RefCountedPtr<ITensorList> objects using the Wrap() factory, dispatching to CPU or GPU backend based on the output type.
Operator trace access is provided through two methods: GetTrace for querying a single trace by operator and trace name (returning std::optional<std::string_view>), and GetTraces for bulk retrieval of all operator traces as a span<daliOperatorTrace_t>. The bulk trace data is lazily constructed and cached on first access.
The C API functions include: daliPipelineOutputsDestroy for cleanup, daliPipelineOutputsGet for retrieving output tensor lists by index, daliPipelineOutputsGetTrace for individual trace queries, and daliPipelineOutputsGetTraces for bulk trace retrieval.
Usage
Use pipeline outputs to access the results of a DALI pipeline run. After calling daliPipelinePopOutputs, use the returned handle to get individual output tensor lists and query operator traces. Destroy the outputs handle when done to release the pipeline's output buffers for reuse.
Code Reference
Source Location
- Repository: NVIDIA_DALI
- File: dali/c_api_2/pipeline_outputs.cc
- Lines: 1-131
Signature
namespace dali::c_api {
class PipelineOutputs : public _DALIPipelineOutputs {
public:
PipelineOutputs(Pipeline *pipe, AccessOrder order);
~PipelineOutputs();
RefCountedPtr<ITensorList> Get(int index);
span<daliOperatorTrace_t> GetTraces();
std::optional<std::string_view> GetTrace(std::string_view op_name,
std::string_view trace_name) const;
};
PipelineOutputs *ToPointer(daliPipelineOutputs_h handle);
} // namespace dali::c_api
// C API functions
daliResult_t daliPipelineOutputsDestroy(daliPipelineOutputs_h h);
daliResult_t daliPipelineOutputsGet(daliPipelineOutputs_h outputs,
daliTensorList_h *out, int idx);
daliResult_t daliPipelineOutputsGetTrace(daliPipelineOutputs_h outputs,
const char **out_trace,
const char *operator_name,
const char *trace_name);
daliResult_t daliPipelineOutputsGetTraces(daliPipelineOutputs_h outputs,
const daliOperatorTrace_t **out_traces,
int *out_trace_count);
Import
#include "dali/c_api_2/pipeline_outputs.h"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| outputs | daliPipelineOutputs_h | Yes | Pipeline outputs handle obtained from daliPipelinePopOutputs |
| idx | int | Yes | Output index (0-based) for tensor list retrieval |
| operator_name | const char * | Yes (trace query) | Name of the operator whose trace to query |
| trace_name | const char * | Yes (trace query) | Name of the specific trace key |
Outputs
| Name | Type | Description |
|---|---|---|
| daliResult_t | enum | DALI_SUCCESS, DALI_NO_DATA (trace not found), or error codes |
| out | daliTensorList_h * | Reference-counted tensor list handle for the requested output |
| out_trace | const char ** | Pointer to trace value string (valid while outputs handle exists) |
| out_traces | const daliOperatorTrace_t ** | Array of all operator trace entries |
| out_trace_count | int * | Number of trace entries |
Usage Examples
Retrieving Pipeline Outputs
#include "dali/dali.h"
// Run the pipeline
daliPipelineRun(pipeline);
// Pop outputs
daliPipelineOutputs_h outputs = nullptr;
daliPipelinePopOutputs(pipeline, &outputs);
// Get the first output as a tensor list
daliTensorList_h tl = nullptr;
daliPipelineOutputsGet(outputs, &tl, 0);
// Use the tensor list...
int num_samples, ndim;
daliTensorListGetShape(tl, &num_samples, &ndim, nullptr);
// Release the tensor list reference
daliTensorListDecRef(tl, nullptr);
// Destroy outputs to release pipeline buffers for reuse
daliPipelineOutputsDestroy(outputs);
Querying Operator Traces
daliPipelineOutputs_h outputs = nullptr;
daliPipelinePopOutputs(pipeline, &outputs);
// Query a specific trace
const char *trace_value = nullptr;
daliResult_t r = daliPipelineOutputsGetTrace(outputs, &trace_value, "my_op", "my_trace");
if (r == DALI_SUCCESS) {
printf("Trace value: %s\n", trace_value);
} else if (r == DALI_NO_DATA) {
printf("Trace not found\n");
}
// Bulk query all traces
const daliOperatorTrace_t *traces = nullptr;
int count = 0;
daliPipelineOutputsGetTraces(outputs, &traces, &count);
for (int i = 0; i < count; i++) {
printf("Op: %s, Trace: %s, Value: %s\n",
traces[i].operator_name, traces[i].trace, traces[i].value);
}
daliPipelineOutputsDestroy(outputs);