notes/bench.md
The Geniex Bench pipeline benchmarks geniex-bench on real Qualcomm hardware via QDC
(Qualcomm Device Cloud) and reports results as a GitHub Actions step summary.
build-sdk --> load-models --> bench (device x model matrix) --> aggregate (per device)
The SDK is cross-compiled for 3 platforms via _build-sdk.yml, producing a
geniex-bench binary for each:
| Platform | Target Device | Binary | Test Framework |
|---|---|---|---|
| Linux ARM64 | QCS9075M (IoT) | geniex-bench | Bash |
| Windows ARM64 | SC8380XP / SC8480XP (Snapdragon X) | geniex-bench.exe | PowerShell |
| Android ARM64 | SM8750 / SM8850 (phone) | geniex-bench | Appium + pytest |
Each platform gets a zip artifact assembled by build_*_artifact() in
sdk/benchmark/qdc/run_qdc_jobs.py:
run_linux.sh or run_windows.ps1) + sample prompts + VLM test image.test_bench.py, utils.py) +
matrix rows + prompts.The model matrix is defined in sdk/benchmark/qdc/bench-models.json
(models across llama_cpp and qairt plugins).
QDC interaction lives in sdk/benchmark/qdc/_qdc.py:
| Function | Purpose |
|---|---|
make_client | Creates an authenticated QDC API client (QDC_API_KEY, app=geniex-ci) |
resolve_target | Maps chipset name (e.g. SM8850) to a QDC target ID |
submit_and_wait | Uploads artifact zip, submits job, polls every 30 s until terminal state. Quota-aware retry with exponential backoff (30 s base, 1 hr budget) |
On-device, all platforms perform the same work:
geniex-bench --matrix-file <tsv> --output-json-dir <out> --chipset <chip>.sdk/benchmark/benchmark.c) runs each cell:
1 warmup + 3 measured repetitions, writing a per-cell JSON with aggregated
stats (median / stdev / min / max for TTFT, prefill tok/s, decode tok/s).QDC_logs/results/ which QDC auto-collects.Orchestrated by bench.yml in 4 jobs:
bench-models.json, emit the matrix + device list.bench-cells-{device}-{model}.render_aggregate() which flattens cells, builds a markdown table, and writes
it to $GITHUB_STEP_SUMMARY.Example output:
## QDC Bench -- SM8850
| Model | Backend | Device | Ctx | ngl | Test | TTFT (ms) | Prefill (tok/s) | Decode (tok/s) |
|-------------|-----------|--------|----:|----:|------------|----------:|----------------:|---------------:|
| Qwen3-0.6B | llama_cpp | cpu | 512 | - | pp42+tg128 | 49.8 +/-2.4 | 102.1 +/-6.2 | 60.9 +/-2.3 |
Standalone geniex-bench archives (binary + runtime libs) are published to S3
on each release. Use the latest URLs to always get the current stable build,
or pin to a specific version tag.
Replace <tag> with the release tag (e.g. v1.2.3):
| Platform | URL |
|---|---|
| Linux ARM64 | https://qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-bench-linux-arm64-<tag>.tar.gz |
| Android ARM64 | https://qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-bench-android-arm64-<tag>.tar.gz |
| Windows ARM64 | https://qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-bench-windows-arm64-<tag>.zip |
# Linux / Android (same binary format, different target device)
curl -fsSL https://qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-bench-linux-arm64.tar.gz | tar xz
./geniex-bench-linux-arm64-*/bin/geniex-bench --help
# Windows (PowerShell)
Invoke-WebRequest https://qaihub-public-assets.s3.us-west-2.amazonaws.com/qai-hub-geniex/geniex-bench-windows-arm64.zip -OutFile bench.zip
Expand-Archive bench.zip -DestinationPath .
.\geniex-bench-windows-arm64-*\bin\geniex-bench.exe --help
Each archive contains bin/geniex-bench (or .exe) plus lib/ with all
required runtime shared libraries (libgeniex, llama_cpp plugin, qairt plugin).