Implementation:NVIDIA DALI Operator Trace Tests
| Knowledge Sources | |
|---|---|
| Domains | Data_Pipeline, C_API |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
The operator trace test suite validates the DALI C API's ability to read operator trace metadata across different executor configurations and input modes.
Description
This file implements parameterized Google Tests for verifying operator trace functionality through the legacy DALI C API. Operator traces are string key-value pairs that operators can emit during execution (via ws.SetOperatorTrace()), and the C API provides daliHasOperatorTrace and daliGetOperatorTrace to query these traces from the workspace after output retrieval.
The test fixture OperatorTraceTest is parameterized with OperatorTraceTestParam, which specifies CPU/GPU queue depths and executor configuration (simple, pipelined uniform, pipelined separate, dynamic). The test constructs a pipeline with a FileReader, and two PassthroughWithTraceOp operators (one CPU, one GPU) that each emit a trace value containing their iteration index. The test verifies that traces are correctly accessible and contain the expected values across 50 iterations.
A derived fixture OperatorTraceTestExternalInput replaces the FileReader with external inputs, feeding random data through daliSetExternalInput before each prefetch cycle. This tests trace correctness when input data is provided externally rather than from a built-in reader. The test suite is instantiated across four executor configurations: simple, pipelined with uniform queues, pipelined with separate queues, and dynamic executor.
Usage
Use these tests to verify that operator trace values are correctly propagated through the pipeline execution and accessible via the C API, particularly when changing executor implementations, queue depth configurations, or input feeding mechanisms.
Code Reference
Source Location
- Repository: NVIDIA_DALI
- File: dali/c_api/operator_trace_test.cc
- Lines: 1-320
Signature
struct OperatorTraceTestParam {
int cpu_queue_depth, gpu_queue_depth;
bool exec_pipelined, exec_async, exec_dynamic;
};
class OperatorTraceTest : public ::testing::TestWithParam<OperatorTraceTestParam> { ... };
class OperatorTraceTestExternalInput : public OperatorTraceTest { ... };
TEST_P(OperatorTraceTest, OperatorTraceTest);
TEST_P(OperatorTraceTestExternalInput, OperatorTraceTestExternalInput);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestSimpleExecutor, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestPipelinedExecutorUniformQueue, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestPipelinedExecutorSeparateQueue, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestDynamicExecutor, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestExternalInputSimpleExecutor, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestExternalInputPipelinedExecutorUniformQueue, ...);
INSTANTIATE_TEST_SUITE_P(OperatorTraceTestExternalInputPipelinedExecutorSeparateQueue, ...);
Import
#include <gtest/gtest.h>
#include "dali/c_api.h"
#include "dali/pipeline/pipeline.h"
#include "dali/test/dali_test_config.h"
#include "dali/test/test_tensors.h"
#include "dali/test/tensor_test_utils.h"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| OperatorTraceTestParam | struct | Yes | Executor configuration (queue depths, async/pipelined/dynamic flags) |
| DALI test data (DALI_EXTRA_PATH) | Filesystem | Yes | JPEG image dataset for FileReader-based tests |
| Random CPU/GPU data | uint8_t buffers | Yes (external input tests) | Randomly generated input data for ExternalSource tests |
Outputs
| Name | Type | Description |
|---|---|---|
| Trace values | const char * | Operator trace strings of the form "test_value{iteration_index}" |
| Test assertions | GTest EXPECT/ASSERT | Validates trace existence and expected string values |
Usage Examples
Querying Operator Traces via C API
daliPipelineHandle h;
daliCreatePipeline2(&h, serialized.c_str(), serialized.length(),
batch_size, num_threads, device_id,
exec_pipelined, exec_async, exec_separated,
cpu_queue_depth, cpu_queue_depth, gpu_queue_depth, 0);
daliPrefetch(&h);
daliShareOutput(&h);
// Check if a trace exists
int has_trace = daliHasOperatorTrace(&h, "MyOperator", "my_trace");
// has_trace: 1 = exists, 0 = not found, -1 = operator not found
// Get trace value
if (has_trace > 0) {
const char *trace_value = daliGetOperatorTrace(&h, "MyOperator", "my_trace");
// Use trace_value...
}
daliOutputRelease(&h);
daliDeletePipeline(&h);
External Input with Trace Verification
// Feed CPU input data
int feed_count = daliInputFeedCount(&h, "OP_TRACE_IN_CPU");
for (int i = 0; i < feed_count; i++) {
std::vector<int64_t> shapes(batch_size, sample_size);
daliSetExternalInput(&h, "OP_TRACE_IN_CPU", CPU,
data_ptr, DALI_UINT8, shapes.data(),
1, nullptr, DALI_ext_default);
}
daliPrefetch(&h);
daliShareOutput(&h);
// Verify trace is accessible after external input feeding
ASSERT_NE(daliHasOperatorTrace(&h, operator_name, trace_name), 0);
const char *trace = daliGetOperatorTrace(&h, operator_name, trace_name);