Finding
expXa costs nothing here: it stays within 2% of PXA 3.1 on both models and produces identical text. PXA 4 is 11–15% faster on the 0.8B, mainly because it decodes about 20% faster. On the 9B, all three engines are within 1% of each other.
Qwen3.5-0.8B Q8_0
| Engine | Input | Prefill tok/s | Decode tok/s | First token | Request | Range |
|---|---|---|---|---|---|---|
| PXA 3.1 | 512 | 7,175.0 | 275.8 | 0.074 | 0.537 | 0.536–0.544 |
| PXA 4.0.1 | 512 | 7,420.0 | 336.0 | 0.071 | 0.456 | 0.451–0.458 |
| expXa | 512 | 7,093.5 | 273.0 | 0.076 | 0.546 | 0.538–0.546 |
| PXA 3.1 | 2,048 | 8,055.7 | 276.5 | 0.258 | 0.721 | 0.719–0.724 |
| PXA 4.0.1 | 2,048 | 8,373.0 | 333.2 | 0.249 | 0.632 | 0.632–0.635 |
| expXa | 2,048 | 8,041.8 | 275.4 | 0.259 | 0.724 | 0.723–0.729 |
| PXA 3.1 | 3,584 | 7,956.4 | 274.0 | 0.458 | 0.927 | 0.925–0.929 |
| PXA 4.0.1 | 3,584 | 8,288.5 | 329.9 | 0.439 | 0.828 | 0.826–0.828 |
| expXa | 3,584 | 7,936.0 | 273.4 | 0.458 | 0.927 | 0.926–0.927 |
All three engines produced the same text at every length and in every round.
Qwen3.5-9B Q4_K_M
| Engine | Input | Prefill tok/s | Decode tok/s | First token | Request | Range |
|---|---|---|---|---|---|---|
| PXA 3.1 | 512 | 2,232.1 | 99.7 | 0.257 | 1.542 | 1.540–1.544 |
| PXA 4.0.1 | 512 | 2,187.9 | 99.4 | 0.256 | 1.542 | 1.538–1.558 |
| expXa | 512 | 2,212.0 | 99.4 | 0.260 | 1.548 | 1.542–1.550 |
| PXA 3.1 | 2,048 | 3,419.8 | 98.9 | 0.631 | 1.924 | 1.924–1.926 |
| PXA 4.0.1 | 2,048 | 3,387.9 | 98.9 | 0.639 | 1.934 | 1.931–1.952 |
| expXa | 2,048 | 3,428.1 | 98.9 | 0.630 | 1.925 | 1.924–1.932 |
| PXA 3.1 | 6,144 | 3,816.0 | 97.8 | 1.639 | 2.949 | 2.947–2.955 |
| PXA 4.0.1 | 6,144 | 3,768.4 | 97.6 | 1.662 | 2.975 | 2.972–2.984 |
| expXa | 6,144 | 3,808.5 | 97.6 | 1.642 | 2.956 | 2.952–2.960 |
PXA 4 produced different text from the other two at 512 and 2,048 tokens, consistently across rounds. PXA 3.1 and expXa matched each other everywhere, and all three matched at 6,144. On forced-length synthetic continuations a text difference isn’t a correctness failure, but it means PXA 4 isn’t output-equivalent here.
Correctness and recovery
- Four short chat checks per arm (arithmetic, grounding in supplied context, field extraction, negation), with natural stopping: 72 of 72 passed.
- Each arm then cancelled a long request, confirmed the slot was released, and answered the arithmetic check twice more: 18 of 18 recovered with matching answers.
- These are sanity checks. They don’t measure reasoning quality or long-context reliability.
Method
- Identical model files, token fixtures and settings for every engine: one slot, Q8_0 KV cache, Flash Attention, all layers on GPU, no speculation.
- 9B: 8,192 context, layers split evenly across both GPUs, 4 generation and 8 batch threads. 0.8B: 4,096 context on one GPU, 2 and 2 threads.
- Three rounds rotating engine, model and length order. Each arm started a fresh server with an unscored warmup.
- Prompt cache off, exactly 128 output tokens at greedy sampling, token counts verified. First-token time is the first non-empty streamed chunk seen by the client.
- No expXa MoE-specific profiles were enabled.
Limits
- The 9B was tested with a reduced context split across two GPUs. Single-GPU, full-context behaviour wasn’t measured.
- One synthetic prompt family, three rounds, one shared host. Small differences shouldn’t be read as general gains.