Skip to content
heliaPROFILER
Examples
HELIA

Profile a model

Get one valid result bundle from a board and know what every line of the terminal panel means. You will learn the shape of a run, the difference between the two cycle totals it prints, and where the arena and binary numbers come from.

An Apollo510 EVB connected to the host over its J-Link USB port. Nothing else: the default transport is RTT over the debug connection, so no serial cable and no power instrument. Validate your setup confirms the probe sees the board.

hpx (pip install helia-profiler) and a clone of the repository for the quickstart config and model, the GNU Arm toolchain, CMake and Ninja on PATH, SEGGER J-Link software, and on Linux the udev rule (Install). hpx doctor must report the toolchain and J-Link as found.

examples/quickstart/hpx_rt.yml:

model:
path: kws_model.tflite
arena_size: 131072
engine:
type: helia-rt
config:
variant: release-with-logs
target:
board: apollo510_evb
toolchain: arm-none-eabi-gcc
profiling:
pmu_counters:
cpu: default
memory: default
per_layer: true
iterations: 3
warmup: 1
power:
enabled: false
output:
format: csv
dir: ./results/results_rt

The model path is relative to the config file, so run from examples/quickstart/ or pass the model on the command line. Every key is on the generated configuration reference.

Terminal window
cd examples/quickstart
hpx profile --config hpx_rt.yml

Or without a file, from anywhere:

Terminal window
hpx profile examples/quickstart/kws_model.tflite --board apollo510_evb --engine helia-rt

The first run resolves and builds the NSX dependency workspace, which takes minutes; later runs reuse it.

The results panel of the nightly case named under Validated on (the Memory and Plan vs measured tables that follow it are on Memory placement; the arena progress bar and the host wall-clock subtitle are omitted):

─────────────────────────────────── Results ────────────────────────────────────
Engine helia-rt
Compatibility qualified
Board apollo510_evb
Layers 13
Total cycles 2,060,239
Clean E2E cycles 2,051,232 (-0.4% vs per-layer sum)
Total MACs 2,656,768
Total OPS 5,321,596
Cycles/MAC 0.78
Parameters 22,604
Top Layers by Cycles
# Operator Cycles % MACs Cyc/MAC
1 CONV_2D 337,348 16.4% 320,000 1.1
2 DEPTHWISE_CONV_2D 216,207 10.5% 72,000 3.0
3 DEPTHWISE_CONV_2D 216,205 10.5% 72,000 3.0
4 DEPTHWISE_CONV_2D 216,194 10.5% 72,000 3.0
5 DEPTHWISE_CONV_2D 216,192 10.5% 72,000 3.0
Arena 29,780 / 32,768 bytes 91%
Model 53,744 bytes
Binary Sections
Section Size
text 278,596
data 154,796
bss 86,260
reserved 365,404
total 885,056
Validity: VALID
╭─ Output → results/… ───────────╮
│ profile_results.csv │
│ summary.json │
│ run_metadata.json │
│ nsx.lock │
│ result_manifest.json │
╰────────────────────────────────╯
  • Clean E2E cycles is the inference cost: the firmware ran the model warm, back to back, with no per-layer instrumentation, and averaged 46 inferences. Total cycles is the sum of the instrumented per-layer rows and is 0.4% higher because every operator was bracketed by a counter read. Publish the clean number (Latency and per-layer).
  • Top Layers by Cycles ranks the per-layer rows; Cyc/MAC divides by the operator’s multiply-accumulates from the host-side model analysis. A depthwise convolution at 3.0 cycles per MAC next to a full convolution at 1.1 is the usual shape: depthwise has less arithmetic per byte moved.
  • Arena 29,780 / 32,768 is the interpreter’s allocation against the configured arena_size; a run that reports the arena does not fit stops before flashing. The quickstart config asks for 131,072 bytes, which is what this model needs with headroom; the nightly case used 32,768.
  • Validity: VALID and an empty issue list mean the run is a measurement. A DEGRADED or INVALID verdict lists codes to look up on the issue codes page.
  • The five files are described on Output files; summary.json has every number above in machine-readable form.
  • Other boards, same config with --board: the same nightly run profiled this model on apollo330mP_evb (2,056,992 clean cycles, Cortex-M55), apollo3p_evb (10,186,141, Cortex-M4, DWT cycle counter only) and apollo4l_blue_evb (8,683,558, Cortex-M4); those bundles ship beside the Apollo510 one. Cortex-M4 boards capture cycles only, not the PMU groups (Boards and targets).
  • More iterations: --iterations 20 --warmup 5 tightens the per-layer median; the clean window is sized separately by window_target_ms.
  • Another engine or toolchain: Compare engines, Compare toolchains.
  • A JSON bundle: --output-format json writes profile_results.json instead of the CSV.
Board apollo510_evb (Apollo510, Cortex-M55, lp clock tier, 96 MHz as recorded in the bundle’s run_metadata.json)
Run nightly hardware validation run 35078330526, 2026-09-16 09:15 UTC, suite complete, hpx 0.1.6 at source commit 0714893
Case apollo510_evb-kws-rt-ns-arm-none-eabi-gcc-rtt-auto, verdict valid, no issues
Model kws_model.tflite, SHA-256 935c513a…bdf038, the same bytes as the quickstart file
nsx modules baseline hpx-neuralspotx-0.8.1-2026-09: nsx-helia-rt helia-rt-v1.20.0 (edb3a25), nsx-cmsis-nn aaeb145, nsx-ambiq-sdk a9f4ec2, nsx-pmu-armv8m 5725c06, nsx-board-apollo510-evb packaged with neuralspotx 0.8.1
Toolchain arm-none-eabi-gcc 15.2.1 (Arm GNU Toolchain 15.2.Rel1), CMake 4.1.2
Differences from the config above the nightly case used arena_size: 32768, pmu_counters: {cpu: default} and output.format: csv; the quickstart config adds the memory group and a larger arena
Bundle examples/results/hardware-validation-2026-09-16/apollo510_evb-kws-rt-ns-arm-none-eabi-gcc-rtt-auto/