Model Explorer overlays
Look at where the cycles go on the graph rather than in a table. hpx writes one overlay JSON per captured counter that Model Explorer renders as a colour over each operator node.
Prerequisites
Section titled “Prerequisites”A result bundle with model_explorer/ in it (the default; output.model_explorer
is true), the .tflite model that produced it, and Model Explorer in a
browser.
Which overlay
Section titled “Which overlay”| File | Value on each node |
|---|---|
model_explorer/me_overlay_<COUNTER>.json |
that counter’s per-layer aggregate, one file per counter captured, for example me_overlay_ARM_PMU_CPU_CYCLES.json, me_overlay_ARM_PMU_INST_RETIRED.json, me_overlay_ARM_PMU_MVE_INST_RETIRED.json |
Each overlay maps graph node ids to that counter’s raw per-layer value and
carries a three-stop gradient (GRADIENT_COST in
report/model_explorer.py): Model Explorer interpolates it across the
range of values in the file, green at the minimum, yellow at the midpoint
and red at the maximum. The colour is relative to the range in that one
overlay, so a node’s colour says nothing about absolute cost and cannot be
compared between two overlays or two runs.
The file is Model Explorer’s node-data format: a top-level key per graph id
(main for a single-subgraph model) holding a name shown in the overlay
selector (the counter name), a results map from node key to
{"value": <number>}, and the gradient list. It is plain JSON, so
jq '.main.results' reads the per-node values when the graph view is not
needed; Parsing outputs
covers the CSV and summary that carry the same numbers with more context.
- Open Model Explorer.
- Load the
.tflitemodel the run profiled (the same file; the overlay matches nodes by operator index). - Choose Add Overlay and pick one of the
me_overlay_*.jsonfiles. - Read the colours: red is the highest value of that counter, green the
lowest. Switch overlays to compare, for instance cycles against
ARM_PMU_L1D_CACHE_MISS_RDto see whether a hot layer is memory-bound. - Check the picture against the table: the reddest node of the cycles
overlay is the first row of
summary.top_layers, and itspctsays how much of the instrumented total it holds. High cycle cost with many cache misses is a reason to investigate memory placement. Low cache misses alone do not prove a layer is compute-bound; compare stalls, instruction counts and the other available counters before attributing the cost.
A layer that ran in several PMU passes has one value per counter, taken from the pass that captured that counter; a counter the SoC could not capture has no overlay file rather than a file of zeros.
Nodes are matched by the original TFLite operator index, the same
source_index that joins MACs on
Output files. heliaRT and TFLM run
operators in graph order, so their overlays use the sequential operator
index (0, 1, 2, …). heliaAOT skips operators such as VAR_HANDLE
without renumbering, so its overlays use the original index from the AOT
operator manifest, or from the label suffix (the 3 in CONV_2D:3) when
the run has no manifest. A layer whose original index cannot be resolved
(a position the AOT manifest does not name, or any run whose manifest
extraction failed) is left out of the overlay rather than painted onto an
unrelated node. ExecuTorch layers name plan instructions, not graph nodes,
so an ExecuTorch run writes no overlay files. Each run replaces the
me_overlay_*.json files in model_explorer/.
Disabling
Section titled “Disabling”hpx profile model.tflite --no-model-exploreroutput: model_explorer: falseThe model_explorer/ directory is then absent and the manifest lists no
overlay export; nothing else in the bundle changes.
Expected output
Section titled “Expected output”A graph whose hottest operators match top_layers in summary.json for
the cycles overlay, and whose colour pattern shifts by counter.
What next
Section titled “What next”PMU counters for what each counter measures; Memory placement when the cache-miss overlay points at weights or activations in a slow tier.