Compiler-First State Space Duality and Portable Autoregressive Caching for Inference
Organizations: Imperial College London
Abstract
High-throughput Mamba-2 inference is usually tied to fused CUDA and Triton kernels, limiting portability across accelerator backends. We show that the state space duality (SSD) recurrence has a compiler-friendly structure: diagonal per-head dynamics, fixed-size chunking, einsum-dominated compute, and static control flow. Expressing this structure in standard JAX primitives gives a single-source inference path with no custom kernels, a registered JAX PyTree cache, and a compiled on-device autoregressive loop. On a single Google Cloud TPU v6e, batch-1 prefill reaches approximately 140 TFLOPS, or 15% model FLOP utilisation (MFU), the roofline ceiling for this regime, and cached decode reaches up to 64% hardware bandwidth utilisation (HBU). At a 4096-token context, cached decode is 27x--36x faster than full-prefix recomputation across five Mamba-2 checkpoints from 130M to 2.7B parameters. The same source runs unmodified on NVIDIA L40S, where cached decode remains sequence-length independent across all model scales. WikiText-103 validation perplexity matches the Triton reference mamba_ssm v2.2.2 within +/-0.0005 points, and hidden states agree to float32 rounding tolerance. Code is available at https://github.com/CosmoNaught/mamba2-jax.
Figures & tables
| Throughput (Tokens/Second) | ||||
|---|---|---|---|---|
| Model | Method | 128 | 1024 | 4096 |
| 130M | Cached (scan) | 1588 | 1635 | 1641 |
| Cached (host) | 662 | 729 | 751 | |
| Non-Cached | 903 | 278 | 56 | |
| 370M | Cached (scan) | 626 | 641 | 641 |
| Cached (host) | 392 | 391 | 390 | |
| Prefill MFU (%) by Prompt Length | |||
| Model | 1024 | 4096 | 8192 |
| 130M | 6.22 | 8.23 | 7.68 |
| 370M | 7.47 | 9.04 | 7.60 |
| 780M | 10.62 | 11.33 | 8.20 |
| 1.3B | 12.53 | 11.67 | 8.39 |
| 2.7B | 15.23 | 12.96 | 9.71 |
| Decode HBU (%) by Sequence Length | ||||||
| Model | 128 | 256 | 512 | 1024 | 2048 | 4096 |
| 130M | 51.62 | 52.29 | 52.87 | 53.13 | 53.26 | 53.32 |
| 370M | 57.88 | 58.65 | 59.07 | 59.29 | 59.32 | 59.32 |
| 780M | 62.07 | 62.59 | 62.80 | 62.87 | 62.93 | 62.99 |
| 1.3B | 61.22 | 61.55 | 61.69 | 61.77 | 61.86 | 61.87 |
| 2.7B | 63.43 | 63.74 | 63.91 | 64.00 | 64.06 | 64.08 |
| Throughput (Tokens/Second) | ||||
|---|---|---|---|---|
| Model | Method | 128 | 1024 | 4096 |
| 130M | Cached (scan) | 240.2 | 267.1 | 314.2 |
| Cached (host) | 178.4 | 141.9 | 188.5 | |
| Non-Cached | 203.3 | 115.8 | 20.3 | |
| 370M | Cached (scan) | 154.3 | 165.1 | 148.0 |
| Cached (host) | 104.1 | 98.8 | 112.3 | |
| Model | Triton PPL | JAX PPL | | | |
|---|---|---|---|
| 130M | 18.7023 | 18.7019 | 0.0004 |
| 370M | 13.1247 | 13.1244 | 0.0003 |
| 780M | 10.8892 | 10.8886 | 0.0005 |
| 1.3B | 9.5708 | 9.5704 | 0.0004 |
| 2.7B | 8.3252 | 8.3250 | 0.0002 |
| Output | Relative Tolerance | Absolute Tolerance |
|---|---|---|
| Last hidden state | ||
| Logits (first 256) |
| Masking Strategy | Prefill (tokens/s) | Output |
|---|---|---|
| Static mask ( jnp.tril ) | 42,631 | Bitwise identical |
| Dynamic row-wise mask ( fori_loop ) | 7,330 ( ) |
| Decay Dtype | Max Absolute Error (Logits) |
|---|---|
| float32 (baseline) | 0.0 |
| bfloat16 | 0.013 |
Appendix figures & tables6 assets
Supplementary material from the paper’s appendix.
Appendix
| Component | Version / Value |
|---|---|
| JAX | 0.9.0 |
| jaxlib | 0.9.0.1 |
| XLA / libtpu (TPU runtime) | Bundled with jaxlib 0.9.0.1 |
| Python | 3.12 |
| Flax (NNX) | 0.12.4 |
| PyTorch (golden outputs) | 2.10.0 |
| Throughput (Tokens/Second) by Sequence Length | |||||||
| Model | Method | 128 | 256 | 512 | 1024 | 2048 | 4096 |
| 130M | Cached | 1588 | 1609 | 1627 | 1635 | 1639 | 1641 |
| Non-Cached | 903 | 898 | 626 | 278 | 132 | 56 | |
| 370M | Cached | 626 | 634 | 639 | 641 | 641 | 641 |
| Non-Cached | 495 | 348 | 205 | 124 | 39 | 18 | |
| 780M | Cached | 318 | 321 | 322 | 322 | 323 | 323 |
| Peak Memory (MB) by Sequence Length | |||||||
| Model | Method | 128 | 256 | 512 | 1024 | 2048 | 4096 |
| 130M | Cached | 545.6 | 545.6 | 545.6 | 545.6 | 545.6 | 545.6 |
| Non-Cached | 565 | 585 | 624 | 702 | 857 | 1169 | |
| 370M | Cached | 1591.9 | 1591.9 | 1591.9 | 1591.9 | 1591.9 | 1591.9 |
| Non-Cached | 1644 | 1696 | 1799 | 2007 | 2422 | 3251 | |
| 780M | Cached | 3322.8 | 3322.8 | 3322.8 | 3322.8 | 3322.8 | 3322.8 |
| JIT Compilation Time (seconds) | |||
| Model | Prefill (1024) | Decode (128) | Decode (4096) |
| 130M | 5.5 | 5.6 | 2.5 |
| 370M | 10.2 | 13.0 | 6.4 |
| 780M | 13.0 | 13.7 | 12.6 |
| 1.3B | 10.2 | 14.9 | 21.4 |
| 2.7B | 15.8 | 19.5 | 43.0 |
| Model | Seq. length | JAX (ms) | Triton (ms) | |
|---|---|---|---|---|
| 130M | 512 | 25.9 | 73.7 | |
| 1024 | 45.2 | 72.4 | ||
| 2048 | 86.7 | 68.0 | ||
| 370M | 512 | 62.8 | 147.0 | |
| 1024 | 115.8 | 128.6 | ||
| 2048 | 229.6 | 151.4 |
Efficient Inference
Efficient inference reduces the compute, memory, latency, or energy needed to produce accurate predictions, posterior estimates, and decisions.
See all 107 papers