CTF to TEF conversion¶
In order to expand the compatibility of the traces received in Common Trace Format (CTF), we created a converter for obtaining them in the Trace Event Format (TEF).
Usage¶
You can run the converter with the following command:
west zpl-prepare-trace \
[-h] -o OUTPUT [--zephyr-base ZEPHYR_BASE] [--build-dir BUILD_DIR] \
[--tflm-model-path TFLM_MODEL_PATH] [--tvm-model-path TVM_MODEL_PATH] \
ctf_trace
There are several optional arguments available:
--zephyr-base
- the script tries to automatically find the Zephyr directory in order to use the metadata file definition of CTF events. If this fails, you have to provide the path or set theZEPHYR_BASE
environmental variable.--build-dir
- the directory storing the results of the build and ram_report.--tflm-model-path
- the provided TFLite Micro model is processed to extract information about its layer and tensors, and the information is converted toMODEL
Metadata event.--tvm-model-path
- the provided microTVM graph JSON file is processed to extract information about model’s layer and tensors, and the information is converted toMODEL
Metadata Event,-o
- the file path which points to the file where the converted trace should be saved. If not provided, the JSON will be printed to STDOUT.
Apart from changing the format, this involves a custom logic which can group elements into Duration events, and extend their arguments (see Converted events). Completely new events can be added to the trace, extending the context, and improving the trace visualization capabilities (see Additional events). Furthermore, the command also converts timestamps from nanoseconds (used in CTF) to microseconds, which are valid for Zeppelin Trace Viewer and Speedscope (it assumes that the timestamps are provided in such unit).
Events¶
Converted events¶
This section describes events that are converted from CTF events, emitted during Zeppelin runtime. Based on those, the trace viewer produces dedicated panels with visualizations (e.g. plot panels).
Zephyr events¶
For default Zephyr events (defined in metadata), the beginning event always gets the _enter
suffix, whereas the ending event gets the _exit
suffix.
These events are marked as B
and E
events, creating Duration event in TEF.
The remaining Zephyr events are of Instant type, but since Speedscope does not support displaying such events, they are also converted to a Duration Event with 1 microsecond of duration.
Example events
{
"name": "isr",
"cat": "zephyr",
"ph": "B",
"ts": 99967.43400000001,
"pid": 0,
"tid": 0
},
"...",
{
"name": "isr",
"cat": "zephyr",
"ph": "E",
"ts": 99980.142,
"pid": 0,
"tid": 0
}
zpl_inference
¶
The Duration event marking the beginning and end of model’s inference.
It is created from the CTF events zpl_inference_enter
and zpl_inference_exit
.
zpl_inference
events examples
{
"name": "zpl_inference",
"cat": "zephyr",
"ph": "B",
"ts": 0.0,
"pid": 0,
"tid": 536912424,
"args": {
"thread_id": 536912424
}
},
"...",
{
"name": "zpl_inference",
"cat": "zephyr",
"ph": "E",
"ts": 110497.391,
"pid": 0,
"tid": 536912424,
"args": {
"thread_id": 536912424
}
}
MODEL::{LAYER_OP}[_{SUBGRAPH_IDX}]_{OP_IDX}
¶
The MODEL::*
Duration event is unique to each layer of a model, described with:
LAYER_OP
- a tag of operation likeCONV_2D
orMAX_POOL_2D
,SUBGRAPH_IDX
- an optional number representing the ID of a subgraph to which a given layer belongs,OP_IDX
- a number representing the ID of the operation in a subgraph.
The event contains:
identifiers like
op_idx
and optionalsubgraph_idx
,tag
with the layer name,thread_id
pointing to the thread that executed this layer,runtime
specifying which runtime was used, andadditional runtime-specific data.
This event is converted from TFLite micro (zpl_tflm_(enter|exit)
) and microTVM (zpl_tvm_(enter|exit)
) events.
MODEL::*
events examples
{
"name": "MODEL::CONV_2D_0_0",
"cat": "zephyr",
"ph": "B",
"ts": 4294973.212,
"pid": 0,
"tid": 536912424,
"args": {
"thread_id": 536912424,
"subgraph_idx": 0,
"op_idx": 0,
"tag": "CONV_2D",
"arena_used_bytes": 15408,
"arena_tail_usage": 88,
"runtime": "TFLite Micro"
}
},
{
"name": "MODEL::CONV_2D_0_0",
"cat": "zephyr",
"ph": "E",
"ts": 4359202.146,
"pid": 0,
"tid": 536912424,
"args": {
"thread_id": 536912424,
"subgraph_idx": 0,
"op_idx": 0,
"tag": "CONV_2D",
"arena_used_bytes": 15408,
"arena_tail_usage": 88,
"runtime": "TFLite Micro"
}
}
MEMORY
¶
The Metadata event with information about a memory region for a given timestamp (ts
).
It is created from the CTF event zpl_memory
.
MEMORY
metadata example
{
"name": "MEMORY",
"cat": "zephyr",
"ph": "M",
"ts": 55.216,
"pid": 0,
"tid": 536937200,
"args": {
"memory_region": "STACK",
"memory_addr": 536950376,
"used": 88,
"unused": 424,
"for_thread_id": 536936848
}
}
CPU_LOAD
¶
The Metadata event defining CPU load (cpu_load
field) for a given timestamp (ts
).
It is converted from the CTF event zpl_cpu_load_event
.
CPU_LOAD
metadata example
{
"name": "CPU_LOAD",
"cat": "zephyr",
"ph": "M",
"ts": 200044.308,
"pid": 0,
"tid": 0,
"args": {
"cpu_load": 534
}
}
DIE_TEMP
¶
The Metadata event providing DIE temperatures (die_temp
array with at most two measurements, in degrees Celsius) for a given timestamp (ts
).
It is converted from the CTF event zpl_die_temp_event
.
DIE_TEMP
metadata example
{
"name": "DIE_TEMP",
"cat": "zephyr",
"ph": "M",
"ts": 300327.025,
"pid": 0,
"tid": 0,
"args": {
"die_temp": [
21.947092056274414,
41.94709014892578
]
}
}
Additional events¶
This section contains events that are not produced during the Zeppelin runtime, but are used to provide additional information for better visualizations.
MEMORY::STATICALLY_ASSIGNED_MEM
¶
The Metadata event informing about the part of RAM (in bytes), used by the compiled objects.
This value is calculated using size from ram_report and subtracting sizes of the memory regions (from MEMORY
events).
The event looks like this:
MEMORY::STATICALLY_ASSIGNED_MEM
metadata example
{
"name": "MEMORY::STATICALLY_ASSIGNED_MEM",
"cat": "zephyr",
"ph": "M",
"pid": 0,
"tid": 0,
"ts": 0,
"args": 14105
}
MEMORY::SYMBOLS
¶
The Metadata event contains the mapping of memory region addresses to their symbols extracted from zephyr.elf
.
It is used to present human-readable description of the regions, e.g. making it easier to trace back to the source code.
Example event:
MEMORY::SYMBOLS
metadata example
{
"name": "MEMORY::SYMBOLS",
"cat": "zephyr",
"ph": "M",
"pid": 0,
"tid": 0,
"ts": 0,
"args": {
"536950376": "_k_thread_stack_zpl_mem_profiling",
"536949352": "tracing_thread_stack",
"536952936": "z_idle_stacks",
"536953256": "z_main_stack",
"536938172": "z_malloc_heap",
"536936540": "_system_heap",
"536936560": "test_k_heap",
"536936512": "test_mem_slab"
}
}
thread_name
¶
The Metadata event is used by Speedscope to associate a thread ID with a name. Apart from describing which thread is shown on the flamegraph, the thread name is also used to provide human-readable label for the thread stack.
One event describes exactly one thread with arguments containing the thread name, assigned to the key name
.
thread_name
metadata example
{
"name": "thread_name",
"cat": "zephyr",
"ph": "M",
"pid": 0,
"tid": 536912424,
"args": {
"name": "main"
}
}
MODEL
¶
The MODEL
Metadata event contains following information:
inputs
- the specification of model inputs, described withname
,shape
anddtype
,outputs
- the specification of model outputs, with the same properties asinputs
,tensors
- the specification of internal data like inputs and outputs of layers, their weights or biases; the properties are the same asinputs
, but with additionalindex
and optionalsubgraph_idx
,ops
- the specification of model operations:op_name
- the name of the operation (e.g.CONV_2D
ortvmgen_default_fused_nn_conv2d_add_nn_relu
),index
- the ID of the operation,inputs
andoutputs
- lists with indices pointing totensors
with input and output data (respectively),inputs_types
andoutputs_types
- the operation’s input and output data types,inputs_shapes
andoutputs_shapes
- the operation’s input and output shapes.
Example event of Magic Wand model for TFLite Micro runtime
{
"name": "MODEL",
"cat": "zephyr",
"ph": "M",
"pid": 0,
"tid": 0,
"ts": 0,
"args": {
"inputs": [
{
"name": "input_1",
"name_long": "serving_default_input_1:0",
"shape": [1, 128, 3, 1],
"shape_signature": [-1, 128, 3, 1],
"dtype": "float32",
"quantization": [0.0, 0],
"quantization_parameters": {
"scales": [],
"zero_points": [],
"quantized_dimension": 0
}
}
],
"outputs": [
{
"name": "out_layer",
"name_long": "StatefulPartitionedCall:0",
"shape": [1, 4],
"shape_signature": [-1, 4],
"dtype": "float32",
"quantization": [0.0, 0],
"quantization_parameters": {
"scales": [],
"zero_points": [],
"quantized_dimension": 0
}
}
],
"tensors": [
{
"name": "serving_default_input_1:0",
"subgraph_idx": 0,
"index": 0,
"shape": [1, 128, 3, 1],
"shape_signature": [-1, 128, 3, 1],
"dtype": "float32",
"quantization": [0.0, 0],
"quantization_parameters": {
"scales": [],
"zero_points": [],
"quantized_dimension": 0
}
},
"..."
],
"ops": [
{
"op_name": "CONV_2D",
"index": 0,
"inputs": [0, 3, 1],
"outputs": [10],
"inputs_types": ["float32", "float32", "float32"],
"outputs_types": ["float32"],
"inputs_shapes": {
"0": [1, 128, 3, 1],
"3": [8, 4, 3, 1],
"1": [8]
},
"outputs_shapes": {
"10": [1, 128, 3, 8]
}
},
"..."
]
}
}