sm280299 commited on
Commit
cadbdbd
Β·
verified Β·
1 Parent(s): a36842c

QHexRT launch article: full-stack NPU inference, not open source

Browse files
Files changed (1) hide show
  1. blog/qhexrt-npu-vs-cpu-lfm2.5-230m.md +50 -88
blog/qhexrt-npu-vs-cpu-lfm2.5-230m.md CHANGED
@@ -1,42 +1,41 @@
1
- # QHexRT: Inference Engine for Qualcomm NPUs
2
 
3
- We shipped MetalRT for Apple Silicon. Now we're bringing the same approach to Qualcomm with **QHexRT**: a custom inference runtime built for **every Qualcomm Hexagon NPU**.
4
 
5
- **QHexRT runs on Qualcomm Hexagon NPUs across the fleet.** More architectures ship continuously. Same-day model support, full NPU performance, one runtime.
6
 
7
- We're building QHexRT with one goal: **same-day NPU support for the best models the community ships.** When a model drops, you should be able to run it on the NPU within hours, not months later.
8
 
9
- **LiquidAI released [LFM 2.5 230M](https://huggingface.co/LiquidAI/LFM2.5-230M) on June 25, 2026.** QHexRT supports it on day one. The NPU bundle is here: [runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU).
10
 
11
- This post is the first public benchmark. We ran LFM 2.5 230M on **Hexagon v81** (Snapdragon 8 Elite Gen-2, SM8850) on both the NPU and the CPU of the same chip, same die, same phone. Both stacks produce identical output. The only variable is speed.
12
 
13
- ## The headline numbers
14
 
15
- - **Prefill: 12,540 tok/s** on the NPU vs 871 on the CPU (Q8_0). **14.4x faster.**
16
- - **Time-to-first-token: 36ms flat** for any prompt up to 512 tokens. The CPU takes 588ms at 512 tokens.
17
- - **Decode: the CPU wins** at 250 tok/s vs 172 on the NPU. At 230M params, decode is memory-bandwidth-bound, and the Oryon CPU pulls more usable bandwidth from DDR on this weight set.
18
- - **End-to-end: the NPU wins** once the prompt exceeds ~1.5x the generation length.
19
 
20
- Both stacks emit the same greedy token chain. QHexRT's W8 graph matched the HuggingFace fp32 oracle at logits cosine 1.000000. This is a speed comparison at equal quality.
 
 
 
 
 
 
21
 
22
- ## Setup
23
 
24
- | Item | Value |
25
- | --- | --- |
26
- | **Device** | Qualcomm SM8850 (Snapdragon 8 Elite Gen-2 class) |
27
- | **NPU** | Hexagon v81 (HTP) |
28
- | **CPU** | 8-core Oryon (up to ~4.4 GHz) |
29
- | **Model** | [LiquidAI/LFM 2.5 230M](https://huggingface.co/LiquidAI/LFM2.5-230M) (229.69M params, hybrid decoder) |
30
- | **NPU bundle** | [runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU) (v81 context binaries, W8) |
31
- | **NPU stack** | QHexRT, W8 weight-only (int8 weights, fp16 activations) |
32
- | **CPU stack** | llama.cpp b1-beac530, Q8_0 + Q4_K_M |
33
- | **Fairness** | HTP clock pinned to TURBO; CPU governor pinned to performance, all 8 cores |
34
 
35
- LFM 2.5 230M is a hybrid decoder: 14 layers (6 GQA-attention + 8 short-convolution), hidden size 1024, 16 query heads / 8 KV heads, 65K vocab, tied lm-head. The small query-head count is what makes GQA-native NPU decode possible here.
36
 
37
- ## Run it
 
 
 
 
 
38
 
39
- Download the v81 NPU bundle from [runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU). It includes the QNN context binaries (decode, prefill, lm-head), embeddings, tokenizer, and manifest. No Python in the hot path.
40
 
41
  ```bash
42
  hf download runanywhere/lfm2_5_230m_HNPU --local-dir lfm2_5_230m_HNPU
@@ -45,86 +44,49 @@ adb shell "cd /data/local/tmp/lfm230 && LD_LIBRARY_PATH=. \
45
  ./qhx_generate lfm2-5-230m.json libQnnHtp.so libQnnSystem.so . 64 'The capital of France is'"
46
  ```
47
 
48
- Stage the QAIRT v81 runtime libs (`libQnnHtp.so`, `libQnnSystem.so`, `libQnnHtpV81Skel.so`/`Stub.so`) and the `qhx_generate` tool into the same directory. See the [QHexRT deploy docs](https://github.com/RunanywhereAI/QHexRT) for details. Context binaries are pinned to Hexagon v81.
49
-
50
- Greedy output matches the source model: `"The capital of France is"` β†’ `" Paris."`
51
 
52
  ## Throughput
53
 
54
- | Engine | Prefill (tok/s) | Decode (tok/s) | Decode (ms/tok) | Peak RAM (MB) |
55
- | --- | ---: | ---: | ---: | ---: |
56
- | **QHexRT NPU** (v81, W8) | **12,540** | 172 | 5.8 | 445 |
57
- | **llama.cpp CPU** Q8_0 | 871 | **250** | 4.0 | 299 |
58
- | **llama.cpp CPU** Q4_K_M | 680 | **264** | 3.83 | 209 |
59
-
60
- Prefill is where the NPU wins by the widest margin. QHexRT runs it as one batched forward over a padded 512-token window, so the cost stays constant regardless of prompt length.
61
 
62
- ![Prefill throughput on SM8850 β€” QHexRT NPU vs llama.cpp CPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU/resolve/main/assets/prefill_throughput.png)
63
 
64
- **Figure 1 β€” Prefill throughput (log scale).** QHexRT on Hexagon v81 hits **12,540 tok/s** prefill. llama.cpp on the same die's Oryon CPU reaches 871 tok/s (Q8_0) and 680 tok/s (Q4_K_M). That is **14.4x** and **18.4x** faster prefill on the NPU.
65
-
66
- Decode tells the opposite story on this 230M model. The CPU wins by 1.45–1.53x. Single-token decode reads the full weight set once per token and does minimal compute. At 230M params it is DDR-bandwidth-bound. The Oryon CPU pulls ~58 GB/s effective bandwidth on this weight set vs ~40 GB/s on the HTP. Larger models shift toward compute-bound decode, where the NPU's HMX units have the advantage.
67
 
68
  ## Time to first token
69
 
70
- | Prompt (tokens) | NPU (ms) | CPU Q8_0 (ms) | CPU Q4_K_M (ms) |
71
- | ---: | ---: | ---: | ---: |
72
- | 16 | **36** | 17 | 26 |
73
- | 128 | **36** | 132 | 188 |
74
- | 512 | **36** | 588 | 753 |
75
-
76
- ![Time to first token vs prompt length β€” flat NPU line vs rising CPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU/resolve/main/assets/ttft_vs_prompt.png)
77
-
78
- **Figure 2 β€” Time to first token vs prompt length.** The NPU holds a flat **~36 ms** TTFT for any prompt up to 512 tokens because prefill runs as one batched forward pass. The CPU must stream every prompt token through the weights, so TTFT grows linearly. At 512 tokens the NPU delivers its first token **16x sooner** than Q8_0 (36 ms vs 588 ms). For prompts under ~30 tokens the CPU is still faster; past that crossover the NPU wins by a widening margin.
79
-
80
- ## End-to-end latency
81
-
82
- End-to-end combines a one-time TTFT with G decode steps:
83
-
84
- | Prompt (tokens) | NPU (ms) | CPU Q8_0 (ms) | CPU Q4_K_M (ms) |
85
- | ---: | ---: | ---: | ---: |
86
- | 16 | 773 | **559** | **513** |
87
- | 128 | 773 | **674** | 675 |
88
- | 512 | **773** | 1130 | 1239 |
89
-
90
- At G=128, the NPU holds constant at 773ms regardless of prompt length. The CPU starts faster on short prompts but its rising prefill cost overtakes the NPU near a ~200-token prompt. A real run (15-token prompt + 128 generated tokens) measured 777ms. The formula predicted 772ms. 1% error.
91
 
92
- The NPU wins end-to-end once prompt length exceeds roughly **1.5x the generation length** (e.g. for G=128, once the prompt passes ~200 tokens).
93
 
94
- ## When each engine wins
95
-
96
- **Use QHexRT (NPU)** for prefill-heavy or latency-sensitive workloads: RAG, summarization, long-context requests, classification, extraction, scoring. The flat TTFT keeps the first token fast regardless of prompt length. The NPU also frees the CPU for the rest of the app and uses less power.
97
-
98
- **Use the CPU** for short-prompt, long-generation chat on tiny models (under ~500M params), where raw decode tok/s dominates and prompts stay well under the crossover.
99
-
100
- Peak RAM: QHexRT NPU 445 MB, llama.cpp Q8_0 299 MB, Q4_K_M 209 MB. The NPU keeps int8 weights, the QNN context, and persistent graph I/O tensors resident.
101
 
102
  ## The model catalog
103
 
104
- [LFM 2.5 230M on Hexagon v81](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU) is the first model in the QHexRT catalog. QHexRT targets all Qualcomm Hexagon NPUs. We're adding models as fast as the community ships them.
105
 
106
- This is one small model on one SoC. The decode result is size-dependent. Larger models are more compute-bound, and we expect the NPU to win decode too as HMX utilization rises and the bandwidth wall recedes.
107
-
108
- Next on the roadmap:
109
-
110
- - **More models.** Qwen3, Gemma 3, Phi-4-mini, and other sub-4B models that fit the NPU's memory budget.
111
- - **W4 quantization.** A working W4 path would roughly halve the per-token bytes, projecting ~300-340 tok/s decode.
112
- - **Power metering.** The CPU numbers come from 8 Oryon cores pinned at max clock. The NPU does the same work at a fraction of the power.
113
 
114
  ## Summary
115
 
116
- - **Day-one NPU support** for LFM 2.5 230M (released June 25, 2026)
117
- - **NPU bundle:** [runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU)
118
- - **12,540 tok/s** prefill (14.4x faster than CPU Q8_0)
119
- - **36ms** flat TTFT for any prompt up to 512 tokens
120
- - **172 tok/s** decode (CPU wins on this 230M model)
121
- - NPU wins end-to-end once prompt length exceeds ~1.5x generation length
122
- - Identical greedy output, W8 logits cosine 1.000000 vs fp32 oracle
123
-
124
- LFM 2.5 230M is the first model in the QHexRT catalog. More models, more SoCs, more benchmarks are coming.
125
 
126
- QHexRT is open source: [github.com/RunanywhereAI/QHexRT](https://github.com/RunanywhereAI/QHexRT)
127
 
128
  ---
129
 
130
- _Benchmarked on Qualcomm SM8850 / Hexagon v81. Model: LiquidAI/LFM 2.5 230M. NPU: QHexRT W8 weight-only, QAIRT 2.47.0.260601. CPU: llama.cpp b1-beac530, Q8_0 + Q4_K_M, 8 threads. Both engines produce identical greedy output._
 
1
+ # QHexRT Is Live: Full-Stack NPU Inference for Qualcomm Hexagon
2
 
3
+ We shipped MetalRT for Apple Silicon β€” the first engine to run LLM, speech, vision, and speech-to-speech in one runtime, entirely on the GPU. Today we're launching **QHexRT** for Qualcomm: the same bet on the NPU.
4
 
5
+ **QHexRT runs inference 100% on the Hexagon NPU.** No Python in the hot path. No CPU fallback during inference. We are building the widest model catalog on any Qualcomm NPU stack, with same-day support for the models the community ships.
6
 
7
+ No one has shipped a single runtime that covers **LLM, VLM, STT, TTS, and embeddings** fully on Qualcomm NPUs. MetalRT did it for Apple Silicon. QHexRT does it for Hexagon.
8
 
9
+ ## First model: LFM 2.5 230M
10
 
11
+ **LiquidAI released [LFM 2.5 230M](https://huggingface.co/LiquidAI/LFM2.5-230M) on June 25, 2026.** QHexRT supports it on day one β€” our first catalog entry. The NPU bundle is here: [runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU).
12
 
13
+ Every tensor in the inference path stays on the HTP: decode graph, prefill graph, lm-head, embeddings. Greedy output matches the source model (`"The capital of France is"` β†’ `" Paris."`).
14
 
15
+ ## All modalities, one NPU runtime
 
 
 
16
 
17
+ | Modality | Status |
18
+ | --- | --- |
19
+ | **LLM** | Live β€” LFM 2.5 230M on Hexagon v81 |
20
+ | **VLM** | In development |
21
+ | **STT** | In development |
22
+ | **TTS** | In development |
23
+ | **Embeddings** | In development |
24
 
25
+ One engine, one deployment model, every modality on the NPU β€” the same architecture MetalRT proved on Apple Silicon, now on Qualcomm.
26
 
27
+ ## The headline numbers (LFM 2.5 230M Β· Hexagon v81)
 
 
 
 
 
 
 
 
 
28
 
29
+ Benchmarked on **Hexagon v81** (Snapdragon 8 Elite Gen-2, SM8850). We also ran llama.cpp on the CPU of the same chip, same die, same phone. Both stacks produce identical output.
30
 
31
+ - **Prefill: 12,540 tok/s** on the NPU vs 871 on the CPU (Q8_0). **14.4x faster.**
32
+ - **Time-to-first-token: 36ms flat** for any prompt up to 512 tokens. The CPU takes 588ms at 512 tokens.
33
+ - **Decode: the CPU wins** at 250 tok/s vs 172 on the NPU. At 230M params, decode is memory-bandwidth-bound.
34
+ - **End-to-end: the NPU wins** once the prompt exceeds ~1.5x the generation length.
35
+
36
+ QHexRT's W8 graph matched the HuggingFace fp32 oracle at logits cosine 1.000000.
37
 
38
+ ## Run it
39
 
40
  ```bash
41
  hf download runanywhere/lfm2_5_230m_HNPU --local-dir lfm2_5_230m_HNPU
 
44
  ./qhx_generate lfm2-5-230m.json libQnnHtp.so libQnnSystem.so . 64 'The capital of France is'"
45
  ```
46
 
47
+ Stage the QAIRT v81 runtime libs and the `qhx_generate` tool into the same directory. Context binaries are pinned to Hexagon v81.
 
 
48
 
49
  ## Throughput
50
 
51
+ | Engine | Prefill (tok/s) | Decode (tok/s) | Peak RAM (MB) |
52
+ | --- | ---: | ---: | ---: |
53
+ | **QHexRT NPU** (v81, W8) | **12,540** | 172 | 445 |
54
+ | **llama.cpp CPU** Q8_0 | 871 | **250** | 299 |
55
+ | **llama.cpp CPU** Q4_K_M | 680 | **264** | 209 |
 
 
56
 
57
+ ![Prefill throughput β€” LFM 2.5 230M on SM8850](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU/resolve/main/assets/prefill_throughput.png)
58
 
59
+ **Figure 1 β€” Prefill throughput (log scale).** QHexRT on Hexagon v81 hits **12,540 tok/s** prefill on LFM 2.5 230M. **14.4x** faster than llama.cpp CPU Q8_0 on the same die.
 
 
60
 
61
  ## Time to first token
62
 
63
+ | Prompt (tokens) | NPU (ms) | CPU Q8_0 (ms) |
64
+ | ---: | ---: | ---: |
65
+ | 16 | **36** | 17 |
66
+ | 128 | **36** | 132 |
67
+ | 512 | **36** | 588 |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
+ ![TTFT vs prompt length β€” LFM 2.5 230M](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU/resolve/main/assets/ttft_vs_prompt.png)
70
 
71
+ **Figure 2 β€” Time to first token (LFM 2.5 230M).** Flat **~36 ms** TTFT on the NPU for any prompt up to 512 tokens.
 
 
 
 
 
 
72
 
73
  ## The model catalog
74
 
75
+ [LFM 2.5 230M on Hexagon v81](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU) is the first entry. We're adding models as fast as the community ships them.
76
 
77
+ Next: **VLM, STT, TTS, embeddings** on Hexagon, more LLM models, W4 quantization, and power metering.
 
 
 
 
 
 
78
 
79
  ## Summary
80
 
81
+ - **QHexRT is live** β€” full-stack NPU inference for Qualcomm Hexagon
82
+ - **100% on NPU** β€” no Python, no CPU fallback during inference
83
+ - **First model:** LFM 2.5 230M ([runanywhere/lfm2_5_230m_HNPU](https://huggingface.co/runanywhere/lfm2_5_230m_HNPU))
84
+ - **12,540 tok/s** prefill Β· **36ms** flat TTFT
85
+ - **All modalities** β€” LLM live; VLM, STT, TTS, embeddings in development
86
+ - **Widest model catalog** for Qualcomm NPUs, expanding continuously
 
 
 
87
 
88
+ Full write-up: [runanywhere.ai/blog](https://www.runanywhere.ai/blog/qhexrt-npu-vs-cpu-lfm2.5-230m-qualcomm-hexagon)
89
 
90
  ---
91
 
92
+ _Benchmarked on Qualcomm SM8850 / Hexagon v81. Model: LiquidAI/LFM 2.5 230M. NPU: QHexRT W8 weight-only, QAIRT 2.47.0.260601._