Skip to main content
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

  • Snapdragon X Elite or X2 Elite device running Windows ARM64. See Supported platforms.
  • PowerShell (any version).
  • A pulled model. Run geniex pull first, or let geniex-bench download on first use via --mm-data-dir.

Step 1: Download and extract

Open PowerShell and run:
windows
Verify the binary starts:
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
Output:
By default 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
Example output (Snapdragon X Elite, Q4_0):
Which backend to pick:
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_0 run against a Q8_0 run. 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 uses ngl=0) against --device npu (which uses ngl=-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 / decode numbers (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
The JSON includes per-run timing and aggregated stats (median / min / max / mean / stdev):

Running a model matrix

To sweep multiple (model, device) combinations in a single session — amortising the plugin init cost — use --matrix-file:
bash
Column order: 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