First profile
Run one profile end to end and read the result. By the end you have a
results/ directory from your own board and know how to read clean timing, layer costs and memory use.
Prerequisites
Section titled “Prerequisites”- Validate your setup passed, or at least
hpx doctoris green andhpx probes listshows your probe. - A LiteRT
.tflitemodel. The commands below useexamples/quickstart/kws_model.tflite, the keyword-spotting model in a source checkout (git clone https://github.com/AmbiqAI/helia-profiler.gitif you installed with uv or pip). Apipinstall into an active environment also bundles a different, smaller model, a tiny CNN, atpython -c "from helia_profiler.examples import tiny_cnn; print(tiny_cnn())"; its layer count and operators differ from the outputs below. - Network access on the first run: neuralSPOT-X resolves and clones the pinned heliaRT and firmware modules into its cache.
1. Run the profiler
Section titled “1. Run the profiler”hpx profile examples/quickstart/kws_model.tflite --board apollo510_evbWith no other flags hpx uses these defaults:
| Setting | Default | Where it is defined |
|---|---|---|
| Engine | helia-rt, resolved from the neuralSPOT-X registry and built from source |
EngineConfig.type in config/__init__.py |
| Toolchain | arm-none-eabi-gcc |
TargetConfig.toolchain |
| Transport | rtt, lossless capture over the J-Link |
TargetConfig.transport |
| Counters | the CPU default group: cycles, instructions, frontend and backend stalls; on a Cortex-M4 board only the DWT cycle count is captured and the rest is reported as reduced | ProfilingConfig.pmu_counters |
| Iterations | 100 inferences after 5 warm-up runs | ProfilingConfig.iterations, warmup |
| Output | ./results/ |
OutputConfig.dir |
Progress prints one line per pipeline stage, which group into the six
blocks on the section overview (configure, analyse, build, flash, capture,
report); a power run adds its own build, flash and capture stages. The
first run is the slow one because of the module fetch and the cold build;
later runs reuse the cached modules and build tree. A second run into the
same --output-dir overwrites the files in place, so give each run its own
directory when you want to keep both. Once a run has succeeded, --offline skips
dependency resolution entirely:
hpx profile examples/quickstart/kws_model.tflite --board apollo510_evb --offline2. Open the result directory
Section titled “2. Open the result directory”results/├── result_manifest.json validity, provenance and artifact digests├── summary.json headline metrics; read this first├── profile_results.csv one row per layer, one column per counter├── run_metadata.json the resolved configuration and host environment└── nsx.lock the exact resolved module lock for this runEach file is written by the report stage from the same capture (nsx.lock
is copied from the build and is always present); the manifest lists every
other file with its digest so a bundle can be checked for completeness
later. The schema of every file is on
Output files.
3. Read timing, layer costs and memory use
Section titled “3. Read timing, layer costs and memory use”Open summary.json. The block below is illustrative: the field names and
shape are the summary schema, the values are placeholders until this page
carries a captured run. Replace them with what your board printed.
{ "schema": "hpx.run-summary", "schema_version": 11, "engine": "helia-rt", "layers": 13, "total_cycles": 0, "latency": { "device_clean_infer_count": 10, "device_clean_infer_avg_cycles": 0, "device_clean_infer_avg_us": 0 }, "overflow_detected": false, "top_layers": [ {"op": "CONV_2D", "cycles": 0, "pct": 0.0}, {"op": "DEPTHWISE_CONV_2D", "cycles": 0, "pct": 0.0} ], "memory": {"arena_size": 131072, "allocated_arena": 0}, "validity": "valid", "issues": []}top_layers carries op, cycles and pct (the share of total_cycles),
written by report/summary.py.
latency.device_clean_infer_avg_cyclesandlatency.device_clean_infer_avg_usare the average cost of one inference in the separate clean window, in cycles and microseconds. Use these for whole-model timing when the capture reports them.total_cyclessums the instrumented layer statistics (medians by default); it is a different measurement. Inference and layer timing explains the boundaries.top_layersnames the operators that dominate. Optimisation effort goes there first.memory.allocated_arenais how much of the tensor arena the runtime used. Use it to choose a smaller arena reservation, then recapture to check allocation still succeeds; the next page shows where to set it. On the first run leavearena_sizeat the engine default and let this number tell you the size.
Before you quote any of them, look at validity and issues. A result is
valid, degraded or invalid; each issue is a structured code explained
on the issue codes page. A degraded result
is still a measurement with a caveat; an invalid one is not a measurement.
4. Look at the per-layer table
Section titled “4. Look at the per-layer table”profile_results.csv has one row per layer and one column per counter.
Open it in a spreadsheet, sort by cycles, and you have the same picture as
top_layers for every layer. Output files lists
every column and its unit, and what result_manifest.json records beyond
the digests. The same data is rendered as a
Model Explorer overlay under
results/model_explorer/ when output.model_explorer is on.
Expected output
Section titled “Expected output”A results/ directory with the five files above and, when the run was
clean, "validity": "valid" and "overflow_detected": false in
summary.json.
Troubleshooting the first run
Section titled “Troubleshooting the first run”What next
Section titled “What next”Configure a run moves these flags into a file you can check in and shows the fields you will change most: arena size, memory placement, counters and iterations.