VisionWorks Toolkit Reference

April 8, 2016 | 1.4 Release

 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Debugging and Profiling

Describes the various mechanisms VisionWorks provides for debugging and profiling an application.

Debugging

VisionWorks has various error checking mechanisms to help developers detect and debug failures caused by incorrect usages of the API, invalid primitive parameters, or resource allocation problems. These mechanisms are: API-based error status code API-based error log callback function Console message log

In the following subsections, these error debug mechanisms are further explained.

API based: Error Status Code

The majority of VisionWorks API functions return a vx_status code that informs you if the function completed with or without error.

  • When there is no error, these functions return VX_SUCCESS.
  • When there is an error, these functions return an error code indicating the problem encountered during the execution of the API. Error codes are defined as enum values in vx_status_e and nvx_status_e types.
vx_status status = vxVerifyGraph(graph);
if (status != VX_SUCCESS) {
fprintf(stderr, "Graph verification failed %d\n", status);
}

Functions that return an object reference (e.g., object creation functions) do not directly return a status code; in these cases, the application can still inquire the status by calling vxGetStatus with the returned object reference as parameter.

fprintf(stderr, "Graph creation failed\n");
}

API based : Error Log Callback Function

The error status code is useful to detect an unexpected error at runtime, but it doesn't convey lots of information and it may not be enough to properly understand and analyze issues at application development time. Some of the API functions perform a complex sequence of operations internally and in this case, a simple error code can not inform you what is the actual problem is in detail. This is, for instance, the case with graph verification (vxVerifyGraph), graph execution (vxProcessGraph) and the execution of any vision primitive in immediate mode such as vxuOpticalFlowPyrLK.

To get more information about any error, it is possible to register a log callback function to a context with vxRegisterLogCallback. The callback will be called when any error occurs within this context. The callback must have an interface defined by vx_log_callback_f .

The execution of the code example given at the end of this section generates the following information:

Error [ref=0x2c7bbf0, status=-10] :
vxVerifyGraph: node[color_convert].parameter[1]: invalid image (dims=640x480,format=VX_DF_IMAGE_YUV4), expected dims=1920x1080,format=VX_DF_IMAGE_YUV4

The call to vxVerifyGraph returned -10 (VX_ERROR_INVALID_PARAMETERS) while the string passed to the callback function informs you on which node of the graph and which particular parameter caused a problem, as well as the detailed reason.

Log callback code example

/* This function has an error since input and output images of the
* node don't have the same dimensions
*/
void function_with_error(vx_context context, vx_image in, vx_image out)
{
/* Single node graph */
vx_graph graph = vxCreateGraph(context);
fprintf(stderr, "Graph creation failed\n");
}
vxColorConvertNode(graph, in, out);
vx_status status = vxVerifyGraph(graph);
if (status != VX_SUCCESS) {
fprintf(stderr, "Graph verification failed %d\n", status);
}
}
void VX_CALLBACK logCallback(vx_context, vx_reference ref, vx_status status,
const vx_char message[])
{
fprintf(stderr, "Error [ref=" VX_FMT_REF ", status=%d] :\n%s\n",
ref, status, message);
}
void main_function(vx_context context, vx_image in, vx_image out)
{
// Register a non reentrant log callback to the context
vxRegisterLogCallback(context, &logCallback, vx_false_e);
// Call a function that will generate an error
function_with_error(context, in, out);
}

Console Message Log

Console Message Log Error reporting through API calls in some cases might be insufficient where the failures are caused by a series of operations combined. VisionWorks provides another layer of status reporting mechanism controlled through an environment variable, called NVX_LOG. The NVX_LOG environment variable enables reporting of various messages directly to the standard output stream (stdout) to be directly generated in the console.

NVX_LOG controls debug messages for certain type of operations, called "zones". You can enable different zone debug messages by setting the NVX_LOG environment variable with the list of zones that must be activated, separated with commas. VisionWorks defines the following zones:

  • error : errors messages
  • warning : warning messages
  • api : API calls
  • data : information about data objects
  • graph : information related to graphs verification, execution and to the execution of primitives in immediate mode
  • memory : memory allocation / deallocation information
  • perf : performance messages
  • misc : messages that do not fit any other category

To enable information reported in all the zones, set the environment variable to:

  • all : activates all console log messages

For instance, under Linux/Bash:

export NVX_LOG=error,graph

For the previous code example, it would generate:

ZONE_GRAPH: {22cd89c0} [0] Create a graph
ZONE_GRAPH: {22cd89c0} [1] No graph options inherited from the NVX_GRAPH env variable
ZONE_GRAPH: {22cd89c0} [1] Created graph object 0x38d8a70 OK
ZONE_GRAPH: {22cd89c0} [0] Create a node org.khronos.openvx.color_convert (enum: 1) in graph 0x38d8a70
ZONE_GRAPH: {22cd89c0} [1] Set parameter color_convert.0 (0x38d9040) : type=IMAGE ref=0x38d7900
ZONE_GRAPH: {22cd89c0} [1] Set parameter color_convert.1 (0x38d9040) : type=IMAGE ref=0x38d81a0
ZONE_GRAPH: {22cd89c0} [1] Created node object 0x38d9040 OK
ZONE_GRAPH: {22cd89c0} [0] Verification of graph 0x38d8a70
ZONE_GRAPH: {22cd89c0} [1] Graph optimization level: 2
ZONE_GRAPH: {22cd89c0} [1] No cycle detected in the graph : OK
ZONE_GRAPH: {22cd89c0} [1] Node parameters validation
ZONE_GRAPH: {22cd89c0} [2] Validate parameters from node 0x38d9040, name = color_convert
ZONE_GRAPH: {22cd89c0} [3] Expected output: IMAGE, dims=1920x1080, format=VX_DF_IMAGE_YUV4
ZONE_ERROR: {22cd89c0} [3] invalid image (dims=640x480,format=VX_DF_IMAGE_YUV4), expected dims=1920x1080,format=VX_DF_IMAGE_YUV4
Note
In the log, {22cd89c0} identifies the thread that generated the message.

Graph Debug and Visualization

Message Logs

OpenVX graphs can be complex objects and they usually require special attention from developers. When there is a problem with a graph, the first thing to do is to activate the log messages for the graph, in addition of messages of warnings and errors.

It can be done this way:

export NVX_LOG=error,warning,graph

Setting Graph Options with an Environment Variable

It can be useful for you to temporarily set graph options; for instance, for disabling all optimizations. All graph options that can be set though the API with the NVX_GRAPH_VERIFY_OPTIONS graph attribute can be set directly though the NVX_GRAPH environment variable. In order to simplify the definition of the NVX_GRAPH environment variable, comma can be used instead of space as a separator.

export NVX_GRAPH=-O0,--dot,dot_
Note
The options set with the NVX_GRAPH environment variable apply to all graphs of the application. In case the application already set options to some of the graphs with the API, by defining the NVX_GRAPH_VERIFY_OPTIONS attribute, the options set by the attribute are considered higher priority.

Visualize the Graph

In order to check that an OpenVX graph is correctly formed, or visualize a graph created by other developers, VisionWorks provides the option of generating a dot representation of graphs in a file. This graph can be visualized by any tool reading dot files, for instance, xdot under Linux/Ubuntu.

The simplest way to activate the dot generation is to set the NVX_GRAPH environment variable;

export NVX_GRAPH=--dot,<file prefix>

Two files are generated per graphs with the graph verified (vxVerifyGraph):

<file prefix>_<graph id>_initial.dot : Graph created by the application
<file prefix>_<graph id>_executed.dot : Graph to be actually executed after verification

Dot Example

dot_inline_dotgraph_1.png

Profiling

Profiling with the API

Graph and node performance counters can be accessed with the API. This is done by querying the VX_GRAPH_ATTRIBUTE_PERFORMANCE attribute for graph objects and the VX_NODE_ATTRIBUTE_PERFORMANCE attribute for node objects. For each objects, the performance counters are available in a vx_perf_t structure that provides information such as the latest, average, maximum measurement time, etc.

Graph and node performance tracking is enabled by default. Since performance measurement can create an overhead at runtime (dependent on the target platform), it can be disabled with the NVX_DIRECTIVE_PERFORMANCE_DISABLE directive. This directive can be set globally to the context (it will then propagate to all graphs and nodes of this context), or set locally to particular graphs and nodes. Performance measurement can be re-enabled with the NVX_DIRECTIVE_PERFORMANCE_ENABLE directive or set back to the default behavior with NVX_DIRECTIVE_PERFORMANCE_DEFAULT.

Note
If the accuracy of graphs performance counters is generally good on all platforms, the accuracy and the reliability of node performance counters is very dependent on the execution target and on graph level optimizations done by VisionWorks.

Example: Performance Counter

void printPerf(vx_node node)
{
vx_perf_t perf;
vxQueryNode(node, VX_NODE_ATTRIBUTE_PERFORMANCE, &perf, sizeof(perf));
printf("Node execution time : %f ms\n", (double)perf.tmp / 1000000.0) ;
}

Example: Disabling Performance Measurement

// Disable performance measurement globally in the context
// Enable performance measurement for a particular graph
// (overwrites the context directive for this particular graph)
vx_graph graph = vxCreateGraph(context);

Profiling with the Console Log

There is the specific perf zone in the console message log that reports performance counters without any need for application code modification.

For instance, under Linux/Bash:

export NVX_LOG=perf

It would output something similar to:

ZONE_PERF: {721807c0} [0] Execution of graph 0x2a06320: last=1.689 ms, avg=1.745 ms, min=1.654 ms, max=2.480 ms, num=18
ZONE_PERF: {721807c0} [1] node color_convert (enum: 1): last=0.186 ms, avg=0.189 ms, min=0.184 ms, max=0.195 ms, num=18
ZONE_PERF: {721807c0} [1] node gaussian_pyramid (enum: 15): last=0.395 ms, avg=0.399 ms, min=0.393 ms, max=0.405 ms, num=18
ZONE_PERF: {721807c0} [1] node optical_flow_pyr_lk (enum: 27): last=0.149 ms, avg=0.150 ms, min=0.126 ms, max=0.186 ms, num=18
ZONE_PERF: {721807c0} [1] node harris_track (enum: 300000): last=0.500 ms, avg=0.507 ms, min=0.498 ms, max=0.601 ms, num=18
Note
Since the perf log zone simply reports OpenVX perf counters, the accuracy of such profiling information is the same as the accuracy of API based performance counters. For instance, if the profiling was deactivated for a graph with the NVX_DIRECTIVE_PERFORMANCE_DISABLE directive, no message is generated in the console log for this graph.

Visual Profiling

VisionWorks uses the NVIDIA Tools Extension Library (NVTX) to generate VisionWorks related events that come in addition of CUDA profiling events. Such information can be visualized with the NVIDIA visual profiler.

This VisionWorks trace generation is activated by setting the NVX_PROF environment variable to nvtx . Under Linux/Bash:

export NVX_PROF=nvtx

In order to enable the generation of VisionWorks specific events, the NVTX library must be installed on the target system. Under Linux, this library is installed with the CUDA toolkit, while under Windows it is installed with the NVIDIA NSight IDE.

There are different ways of collecting the profiling information and displaying them. An approach that works on both Tegra and Desktop systems is to use nvprof on the target system to generate a profiling log, and then to import it with the NVIDIA visual profiler (nvvp) running on a development computer.

Under Linux with the Tegra TX1 target system:

Target System : Tegra X1

export NVX_PROF=nvtx
/usr/local/cuda/bin/nvprof --output-profile profile.log <my_application>
Note
With DrivePX, you may be required to launch the nvprof command with sudo .

Desktop Development System (in the NVIDIA Visual Profiler)

File
+-> Import
+-> Nvprof
+-> Single or Multiple process
+-> Remote connection and select the remote profile.log file
+-> Finish

Visual Traces Example

VisionWorks specific information is in the 'Markers and Ranges' section of the time chart created by the NVIDIA Visual profiler. VisionWorks ranges are generated for API calls, node execution, and memory movements. From this kind of time chart, application developers can see the relationship between the calls to the VisionWorks library and the CUDA workload.

Note
The range for nodes in the time chart corresponds to the CPU code executed for nodes. Due to the asynchronous execution of CUDA kernels with regard to the CPU, there will often be a shift between a VisionWorks node execution range and the corresponding CUDA workload. This is visible in the following time chart example.
nvvp_trace.png