geniex-bench measures raw inference throughput — TTFT, prefill speed, and decode speed — on real Snapdragon hardware. It is a standalone binary with no CLI dependency: download the archive, extract, and run.
Prerequisites
- Windows ARM64
- Linux ARM64
- Snapdragon X Elite or X2 Elite device running Windows ARM64. See Supported platforms.
- PowerShell (any version).
- A pulled model. Run
geniex pullfirst, or letgeniex-benchdownload on first use via--mm-data-dir.
Step 1: Download and extract
- Windows ARM64
- Linux ARM64
Open PowerShell and run:Verify the binary starts:
windows
windows
To pin a specific version, replace the URL with a versioned one — see Pinning a version.
Step 2: Run your first benchmark
The minimum required flags are--plugin, --device, and -m. The model argument accepts either a local path or a model-manager id (downloaded automatically on first use):
- Windows ARM64
- Linux ARM64
windows
geniex-bench runs 1 warmup + 5 measured repetitions with 512 random input tokens and generates 128 tokens at temperature 0.0 (deterministic). Numbers are aggregated as median ± stdev across the 5 runs.
Step 3: Compare compute backends
Run the same model with--device cpu, --device npu, and --device hybrid to find the fastest path for your workload.
- Windows ARM64
- Linux ARM64
windows
Qualcomm AI Hub Models (
--plugin qairt) run on NPU only — --device cpu, gpu, or hybrid are silently coerced to npu.Reading the numbers
Every[ok ] line reports three metrics:
ttft and prefill are dominated by parallelism (batch work on NPU/GPU); decode is dominated by memory bandwidth (one token at a time, every weight read once per step). On Snapdragon, hybrid closes the gap between the two phases by routing each op to its best backend.
For --plugin qairt, prompt_tokens and prefill_tps are reported over the padded length (ceil(n / 128) × 128) because the QAIRT engine pads input ids to 128-token chunks. This is expected — the padded count reflects the work the engine actually performed.
Comparing models fairly
Hold these variables constant when comparing two models or configs:
The defaults are already set for reproducible comparisons (temperature 0.0, seed 42, 5 measured repetitions). Change any of them with care — a higher
-n captures more of the decode curve, while a higher -c tests the model under a longer context.
Common mistakes:
- Comparing a
Q4_0run against aQ8_0run. The larger file has more weight data to load per decode step, so it will be slower regardless of compute backend. - Comparing
--device cpu(which usesngl=0) against--device npu(which usesngl=-1, all layers offloaded). If you want a pure CPU baseline, always use--device cpu. - Forgetting to re-run after a model pull. The first run includes download time in wallclock but not in the reported
ttft/prefill/decodenumbers (which are measured inside the engine), so the numbers are still valid — but the full session is slower.
Saving results to JSON
Add--output-json to write a machine-readable report:
bash
Running a model matrix
To sweep multiple(model, device) combinations in a single session — amortising the plugin init cost — use --matrix-file:
bash
cell_id, plugin, device, model_path_or_id. Each row produces one JSON file in --output-json-dir.
Pinning a version
The URLs above always resolve to the latest stable release. To pin a specific version, replace the filename with a versioned one (e.g.v0.3.19):
Next steps
- CLI reference —
geniex inferflags and the--computealiases. - Platforms & runtimes — which chipsets and runtimes are supported.
Was this page helpful?