Tracking issue: #91 (proposal + planned scope).
This document describes the TurboQuant+ (TQ+) integration in Atlas: what changed vs upstream, why each piece matters, before/after numbers, and exactly how to reproduce them.
It's deliberately long because the change is large (~12 kernel files, 9
new KvCacheDtype variants, per-side cache-pool refactor, two new host
drivers) and because reviewers should be able to A/B every claim from a
fresh clone.
Primary upstream research dumping ground for the TQ+ work cited below
(across the Rademacher signs, matched-norm L2, sparse V, asymmetric K/V,
InnerQ, weight pre-rotation, and the broader paper set):
TheTom/turboquant_plus.
The llama.cpp implementation reference is the sibling repo
TheTom/llama-cpp-turboquant.
If you only want the headline (single sentence): TQ+ ships canonical-form
TurboQuant kernels + Turbo2 (was crashing on upstream) + 9 asymmetric
KvCacheDtype variants + per-side cache pool refactor + 9 enum-coverage
unit tests. On Qwen3.6-35B-FP8 at greedy decode, output is byte-identical
to upstream on the symmetric line — i.e. zero perf or quality regression;
the kernel-level math fixes are correct on paper (-DTQ_PLUS_SIGNS,
matched-norm L2, real Turbo3 prefill kernel) but greedy decoding on this
model's attention scores absorbs the numerical differences without
flipping argmax winners. The value of this PR is the new capabilities
and the dispatcher safety nets, not a benchmark win on the existing
symmetric dtypes.
Atlas already shipped a TurboQuant variant of the KV cache (Walsh-Hadamard
rotation + Lloyd-Max codebook with per-group FP8 scales) under
--kv-cache-dtype turbo{3,4,8}. That implementation was a strictly weaker
form of the TurboQuant paper (Zandieh et al., arXiv:2504.19874, April
2025):
- Plain WHT (no sign mask). The paper's Randomized Hadamard Transform applies a random sign vector before the WHT so that the rotation is a true uniform-random orthonormal transform (a uniform random rotation, in the limit). Without the sign mask the rotation is deterministic and does not Gaussianise the coordinate marginals, which is the property that lets a fixed Lloyd-Max codebook attain near-optimal distortion.
- Per-group
amaxscaling. The codebook-friendly L2-minimising scale is||original|| / ||reconstructed||, notMAX / amax. - Turbo3 prefill routed through the NVFP4_64 paged-prefill kernel, which reads 4-bit nibbles. Turbo3 stores 3-bit packed data (8 values per 3 bytes); the nibble reads silently sampled wrong codebook indices.
TurboQuant+ ("TQ+") is the beyond-Google research line published as
TheTom/turboquant_plus
(the umbrella research repo, ~15 papers + reference implementations
across multiple downstream engines) with the llama.cpp engine
reference at
TheTom/llama-cpp-turboquant.
The pieces ported into Atlas in this work:
| Feature | TQ+ paper | Atlas commit |
|---|---|---|
| Canonical Randomized Hadamard signs | TurboQuant paper (Zandieh et al., arXiv:2504.19874) | kernel commit |
| Matched-norm L2 correction | matched-norm-l2.md |
kernel commit |
| Sparse V dequant (attention-gated row skip) | sparse-v-dequant.md |
kernel commit |
| fp16 centroid LUT (halves shmem) | TQ+ optimisation | kernel commit |
| Turbo2 — 2-bit Lloyd-Max codebook | low-bit-codebooks.md |
kernel commit |
| Real Turbo3 prefill (fixes NVFP4 misroute) | (Atlas-specific fix) | kernel commit |
| Bf16K + Turbo3V safer-asym | asymmetric-kv-compression.md |
kernel commit |
| InnerQ per-channel Q/K equalisation | inner-q.md |
both commits |
| 256/512 sign arrays + weight pre-rotation | TQ+ scaling work | both commits |
| Boundary V dtype (LA-V7 substrate) | layer-aware-v-compression.md |
Rust commit |
| File | Why |
|---|---|
kernels/gb10/common/tq_plus_signs.cuh |
Vendored seed=42 Rademacher sign tables (128/256/512). Byte-identical to TURBO_WHT_SIGNS{1,2} in turbo-quant.cuh from the llama.cpp fork. |
kernels/gb10/common/wht_bf16.cu |
TQ_PLUS_SIGNS-gated S2·H·S1 path for hd=128 + new wht_bf16_inplace_inv since (S2·H·S1)·(S2·H·S1) ≠ I when S1 ≠ S2. |
kernels/gb10/common/reshape_and_cache_turbo.cu |
Matched-norm L2 correction across turbo2/3/4 write paths; Turbo2 (2-bit, 4 values/byte) write kernel; combined Bf16K+Turbo3V write kernel. |
kernels/gb10/common/paged_decode_attn_turbo{2,3,4,8}*.cu (9 files) |
fp16 __half LUT (halves shmem) + sparse V gated on per-row softmax exp factor on both remainder and BC=4 batched paths. |
kernels/gb10/common/paged_decode_attn_turbo2_128.cu (new) |
hd=128 Turbo2 decode. |
kernels/gb10/common/paged_decode_attn_bf16k_turbo3v_128.cu (new) |
Combined K-bf16 + V-turbo3 decode at hd=128. |
kernels/gb10/common/inferspark_prefill_paged_turbo{2,3}.cu (new) |
Real prefill kernels for Turbo2 (didn't exist) and Turbo3 (replaces NVFP4 misroute). |
kernels/gb10/common/inferspark_prefill_paged_bf16k_turbo3v.cu (new) |
Asymmetric K-bf16 / V-turbo3 prefill. |
kernels/gb10/common/prefill_paged_compute_asym.cuh (new) |
FA template with per-side LOAD_K_TILE / LOAD_V_TILE macro hooks — lets future asym combos (Bf16K+Turbo4V, Fp8K+Turbo3V, ...) reuse the FA pipeline by supplying different load macros. |
kernels/gb10/common/tq_plus_innerq.{cu,cuh} + _apply.cu (new) |
InnerQ device state, calibration accumulator, Q pre-WHT and K post-WHT scale apply. |
kernels/gb10/*/nvfp4/KERNEL.toml |
Register the new modules for every model target. |
| File | Why |
|---|---|
crates/spark-runtime/src/kv_cache.rs |
9 new KvCacheDtype asym variants + kv_pair() / is_asymmetric() / FromStr aliases. Per-side k_block_bytes_for_layer / v_block_bytes_for_layer APIs so asym pools can size independently. |
crates/spark-runtime/src/kv_cache/paged_impl.rs |
Per-side K/V pool allocation; k_block_stride_bytes_for_layer / v_block_stride_bytes_for_layer exposed for kernel launchers. |
crates/spark-runtime/src/kv_cache/tests_tq_plus.rs (new) |
ALL_VARIANTS / ASYM_VARIANTS / SYM_VARIANTS arrays force new dtypes to be added to tests when added to the enum. Pins per-dtype block-byte arithmetic. |
crates/spark-model/src/layers/qwen3_attention/decode/write_kv_cache.rs |
Symmetric turbo write w/ WHT bookend (Turbo2/3/4/8) + asym Bf16K+Turbo3V dispatch + InnerQ K-side apply. |
crates/spark-model/src/layers/qwen3_attention/decode/run_paged_decode.rs |
Turbo decode dispatch incl. asym. |
crates/spark-model/src/layers/qwen3_attention/decode/attention_forward.rs |
V-type-aware iWHT guard + InnerQ Q-side apply. |
crates/spark-model/src/layers/qwen3_attention/prefill/paged_attn.rs |
Turbo2 + Bf16K+Turbo3V + real Turbo3 prefill routing. |
crates/spark-model/src/layers/qwen3_attention/{init,types,mod}.rs |
New KernelHandle fields + loaders + module exports. |
crates/spark-model/src/layers/qwen3_attention/innerq_driver.rs (new) |
InnerQDriver::from_env() reads TURBO_INNERQ=N + TURBO_INNERQ_STRENGTH. start() at boot, maybe_finalize(128) per scheduler chunk (idempotent kernel-side). |
crates/spark-model/src/weight_loader/qwen35/load_layers/tq_plus_weight_rotation.rs (new) |
apply_canonical_rotation_inplace helper. Wired into attention_arms.rs between sharding and NVFP4 quant for Q/K/V projections. Gated on TQ_PLUS_WEIGHT_ROTATION=1. |
crates/spark-server/src/main_modules/{kv_dtypes.rs,serve_phases/kv_cache.rs} + crates/spark-model/src/factory/build.rs |
boundary_dtype parameter on build_layer_kv_dtypes (LA-V7 substrate). |
tests/test_kv_dtype_smoke.py (new) |
Per-dtype container start + 64-tok generation smoke. Catches dispatch-arm fall-through that unit tests can't (e.g. the original Turbo2 → FP8 ABI mismatch). |
All numbers were measured on:
- Hardware: NVIDIA GB10 (ASUS Ascent GX10), 128 GB unified memory
- Model:
Qwen3.6-35B-FP8at/home/pidtom/models/qwen3.6-35b-fp8 - OS: Ubuntu 24.04 inside the Atlas runtime container
- Driver/CUDA: NVIDIA driver supporting CUDA 13.0, container base
nvidia/cuda:13.0.0-runtime-ubuntu24.04
git clone <atlas-repo> && cd atlas
git checkout feature/tq-plus-clean # or whichever branch carries the integration
docker build -f docker/gb10/Dockerfile -t atlas-gb10-tqplus .
# ~8 min cold (cargo build --release -p spark-server inside builder stage)For each dtype D in {bf16, fp8, turbo2, turbo3, turbo4, turbo8} (and
the asym variants below), start a fresh container:
docker stop atlas-bench 2>/dev/null; docker rm atlas-bench 2>/dev/null
docker run -d --name atlas-bench --gpus all --ipc=host \
-p 8889:8888 -v /path/to/qwen3.6-35b-fp8:/model \
-e RUST_LOG=warn \
atlas-gb10-tqplus \
serve --model-from-path /model \
--port 8888 --bind 0.0.0.0 --max-seq-len 32768 \
--kv-cache-dtype $D --kv-high-precision-layers 0Wait for /v1/models to respond, then run the bench harness:
python3 tests/atlas_matrix_no_hp.py --dtypes $D --out /tmp/$D.jsonThe harness (in tests/atlas_matrix_no_hp.py; the script started life as
ad-hoc local tooling at /tmp/atlas_matrix_no_hp.py on the original test
host and the same code is reproduced here for reviewer convenience) does
4 things per dtype:
- PPL similarity: Continues a fixed WikiText Manhattan-Project
prompt for 64 tokens and reports
difflib.SequenceMatcherratio against the reference completion ("J. Robert Oppenheimer was the director of the Los Alamos Laboratory that designed the actual bombs."). Higher is better; 0.84 is the baseline. - Decode short: 3 calls of
"Explain attention."at 256 tokens. Median tok/s. - Prefill 8K: 3 calls of an 8000-character prompt at
max_tokens=1. Reportsprompt_tokens / wall_time. - Decode after 8K: 2 calls of the same 8K prompt at
max_tokens=128. This is wall-time including prefill, NOT steady-state decode rate.
python3 tests/test_kv_dtype_smoke.py \
--image atlas-gb10-tqplus \
--model-path /path/to/qwen3.6-35b-fp8Iterates every dtype, starts a container, generates 64 tokens, checks non-empty completion. Distinguishes load-time SKIP (model weights don't fit the K-side dtype) from runtime FAIL (kernel dispatch crash). Total ~3 min per dtype × 15 dtypes.
docker run --rm --entrypoint /bin/bash \
-e ATLAS_SKIP_BUILD=1 -e CUDARC_CUDA_VERSION=13000 \
-v $(pwd):/atlas \
atlas-gb10-tqplus-dev \
-c "cd /atlas && cargo test -p spark-runtime --tests kv_cache::"Expected: test result: ok. 32 passed; 0 failed.
All numbers in this section are from tests/atlas_bench_comprehensive.py
on Qwen3.6-35B-FP8, single GPU, --max-seq-len 32768 --kv-high-precision-layers 0. Per-metric median across the harness's
repeated calls (5 for prefill + decode_short, 3 for dec_after_8K).
PPL sim is difflib.SequenceMatcher ratio against the WikiText
Manhattan-Project reference continuation — the same fixed prompt
across every run so deltas are apples-to-apples.
pre_2K / 8K / 16K are prefill throughput at max_tokens=1 for
prompts that produce ≈ 405 / 1595 / 3177 input tokens respectively.
dec_short is 256-token completion after a short prompt.
dec_after_8K is 128-token completion after an 8K-token prefill —
wall-time including the prefill, not steady-state decode rate.
It's retained because it's what tests/atlas_matrix_no_hp.py in the
existing repo already reports.
Reproduce one cell:
python3 tests/atlas_bench_comprehensive.py \
--image atlas-gb10-tqplus \
--model-path /path/to/qwen3.6-35b-fp8 \
--config-name "tqplus-default" \
--dtypes turbo3 \
--out /tmp/turbo3.json| dtype | PPL sim | dec_short | pre_2K | pre_8K | pre_16K | dec_after_8K |
|---|---|---|---|---|---|---|
| fp8 | 0.8485 | 72.15 | 627.97 | 1239.06 | 1402.00 | 41.65 |
| nvfp4 | 0.8485 | 72.10 | 636.28 | 1239.39 | 1410.56 | 41.53 |
| bf16 | 0.8485 | 71.89 | 630.69 | 1227.54 | 1390.46 | 40.87 |
| turbo8 | 0.8384 | 71.73 | 640.08 | 1248.85 | 1416.28 | 41.11 |
| turbo4 | 0.8384 | 71.62 | 638.01 | 1238.62 | 1403.65 | 40.94 |
| turbo3 | 0.8384 | 71.65 | 634.15 | 1230.51 | 1400.57 | 40.85 |
| turbo2 | 0.6465 | 71.46 | 692.35 | 1336.50 | 1519.93 | 41.56 |
Two columns to draw your eye to:
- PPL sim is uniform at 0.848 / 0.838 across every non-Turbo2 dtype. The 0.01 gap between bf16/fp8/nvfp4 (0.848) and turbo3/4/8 (0.838) is within the harness's tokeniser-level granularity at this prompt length (one different output token can flip the SequenceMatcher ratio by ~0.01).
- Turbo2 prefill is the fastest at every context length: 692 / 1337 / 1520 tok/s vs ~635 / 1235 / 1405 for everything else. That's +8-9% prefill throughput at the cost of PPL sim 0.647 — the expected 2-bit Lloyd-Max quality penalty.
This is the table that drove the headline framing above. Baseline
column ran against a clean Docker image built from upstream at
87b7bb3 (no TQ+ changes); TQ+ column is this branch with no env
knobs set. Same harness, same machine, same fixed Manhattan-Project
prompt, same greedy decoding.
| dtype | PPL sim (base → TQ+) | pre_2K (base → TQ+) | pre_8K (base → TQ+) | pre_16K (base → TQ+) | dec_after_8K (base → TQ+) |
|---|---|---|---|---|---|
| fp8 | 0.8485 → 0.8485 | 623.94 → 627.97 | 1219.05 → 1239.06 | 1377.74 → 1402.00 | 41.28 → 41.65 |
| nvfp4 | 0.8485 → 0.8485 | 621.90 → 636.28 | 1208.02 → 1239.39 | 1366.80 → 1410.56 | 41.07 → 41.53 |
| bf16 | 0.8485 → 0.8485 | 629.90 → 630.69 | 1229.35 → 1227.54 | 1394.17 → 1390.46 | 40.94 → 40.87 |
| turbo3 | 0.8384 → 0.8384 | 640.13 → 634.15 | 1249.94 → 1230.51 | 1416.13 → 1400.57 | 41.28 → 40.85 |
| turbo4 | 0.8384 → 0.8384 | 642.51 → 638.01 | 1252.60 → 1238.62 | 1417.42 → 1403.65 | 41.22 → 40.94 |
| turbo8 | 0.8384 → 0.8384 | 634.50 → 640.08 | 1223.43 → 1248.85 | 1389.64 → 1416.28 | 40.95 → 41.11 |
| turbo2 | (CUDA-717 crash → 0.6465) | (crash → 692.35) | (crash → 1336.50) | (crash → 1519.93) | (crash → 41.56) |
Plain reading of the table:
- PPL sim is identical to upstream on every symmetric dtype (0.8485
for fp8/nvfp4/bf16, 0.8384 for turbo3/4/8). We verified the generated
64-token completion text is byte-identical between upstream and TQ+ on
fp8, turbo3, and turbo4. The kernel-level math IS different (verified:
upstream KERNEL.toml does not have
-DTQ_PLUS_SIGNS, upstream reshape_and_cache_turbo.cu has no matched-norm L2, upstream routes turbo3 prefill through NVFP4_64 4-bit nibble reads), but the differences in intermediate attention scores are small enough that greedy decoding picks the same argmax tokens. To detect a quality delta from these fixes you would need (a) longer generation where small drift accumulates, (b) temperature-sampling, or (c) a model with wider per-channel variance distributions in K/V. - Throughput is within ±2% across the board — also within the harness's run-to-run noise. The TQ+ kernels do not regress perf.
- Turbo2 is the only row with a meaningful before/after delta:
on upstream the dispatcher silently routes
--kv-cache-dtype turbo2through the FP8 reshape ABI on the Turbo2 kernel handle, producing CUDA_ERROR_INVALID_ADDRESS_SPACE (717) at the first full-attention layer. TQ+ adds Turbo2 to the symmetric turbo dispatch arm; on the same prompt Turbo2 produces a coherent 28-token completion at 692 / 1337 / 1520 tok/s prefill — the fastest of any dtype tested at every context length, with the expected 2-bit Lloyd-Max quality penalty.
So the quality and throughput part of "before/after" is parity at this scale. The capability part of "before/after" is real (Turbo2, plus the asymmetric variants below).
The branch ships two off-by-default env knobs: TURBO_INNERQ=N (per-
channel Q/K equalisation calibrated over N tokens) and
TQ_PLUS_WEIGHT_ROTATION=1 (rotates Q/K/V projection weights once at
load time, drops 160 runtime WHT launches per decode token).
Same harness, turbo3 only, varying env config:
| config | PPL sim | dec_short | pre_2K | pre_8K | pre_16K | dec_after_8K |
|---|---|---|---|---|---|---|
| default | 0.8384 | 71.65 | 634.15 | 1230.51 | 1400.57 | 40.85 |
| +InnerQ | 0.8384 | 71.66 | 640.41 | 1239.37 | 1406.59 | 40.94 |
| +WeightRot | 0.8485 | 70.66 | 620.72 | 1224.67 | 1390.49 | 40.54 |
| +Both | 0.8485 | 71.37 | 632.78 | 1237.70 | 1393.04 | 40.75 |
Honest readout: on Qwen3.6-35B-A3B specifically, the env knobs don't
move the needle materially. +InnerQ is a no-op (the model's per-
channel variance is already flat after the WHT, so the calibration
converges to identity scales). +WeightRot nudges PPL up by 0.01 at
a ~1-2% prefill cost. Both knobs are wired and active — they may
matter more on models with wider per-channel variance distributions
(Qwen3-Next-80B, MiniMax-M2), which is the follow-up bench. For
Qwen3.6-A3B specifically the default config is the right choice.
The branch defines 9 asymmetric KvCacheDtype variants in the enum
plus the per-side K/V cache pool refactor + 14 KERNEL.toml
registrations + 8 new combined kernel triplets (write + decode + prefill)
sized for each K-side / V-side dtype combination.
The combinations land as three families:
Safer-asym (K kept at baseline precision, V compressed) — the
production-recommended frontier per asymmetric-kv-compression.md in
the TQ+ paper set:
Bf16KTurbo3V,Bf16KTurbo4V,Bf16KTurbo2VFp8KTurbo3V,Fp8KTurbo4V,Fp8KTurbo2V
Both-sides compressed — for models / contexts where K-side bandwidth also dominates:
Turbo4KTurbo3V,Turbo4KTurbo8V,Turbo3KTurbo8V
Per-side cache pool refactor (crates/spark-runtime/src/kv_cache.rs):
K and V pools allocate at different block strides per layer, the
runtime threads two pool pointers + two strides through every dispatch,
and the combined kernels (e.g.
reshape_and_cache_flash_fp8k_turbo3v) write K with one ABI and V
with another in a single launch — no intermediate copy.
The 6 asym variants whose K-side is compatible with FP8 attention
weights run end-to-end on Qwen3.6. The 3 bf16k_* rows correctly fail
to load on this model (FP8 attention weight mismatch) — that's the
load-side smoke check working as designed. Numbers measured against
the same tests/atlas_bench_comprehensive.py harness.
| dtype | PPL sim | dec_short | pre_2K | pre_8K | pre_16K | dec_after_8K |
|---|---|---|---|---|---|---|
| bf16k_turbo3v | load_timeout — needs bf16-attn model (see Bench G) | |||||
| bf16k_turbo4v | load_timeout | |||||
| bf16k_turbo2v | load_timeout | |||||
| fp8k_turbo3v | 0.8485 | 72.30 | 641.19 | 1249.05 | 1415.89 | 41.28 |
| fp8k_turbo4v | 0.8384 | 71.98 | 636.42 | 1240.02 | 1403.23 | 41.03 |
| fp8k_turbo2v | 0.6263 | 72.16 | 631.95 | 1232.50 | 1390.13 | 40.97 |
| turbo4k_turbo3v | 0.8485 | 72.01 | 638.85 | 1242.65 | 1410.52 | 41.04 |
| turbo4k_turbo8v | 0.6465 | 71.96 | 638.85 | 1241.52 | 1402.76 | 40.99 |
| turbo3k_turbo8v | 0.6869 | 71.92 | 634.67 | 1234.47 | 1398.72 | 40.72 |
Headline rows: fp8k_turbo3v and turbo4k_turbo3v both hit
0.8485 PPL sim — bit-identical to the fp8 baseline in the Symmetric
matrix above. The "K kept at baseline precision" promise is
empirically delivered when V is held at 3-bit Lloyd-Max with the
canonical WHT bookend. fp8k_turbo4v (4-bit V) holds 0.8384.
fp8k_turbo2v (2-bit V) drops to 0.6263 — same quality penalty as
the symmetric turbo2 row (0.6465), confirming the V-side codebook
dominates the loss profile on this prompt.
Throughput on the asym variants matches the symmetric line to within ±1% across every context length — the per-side cache pool refactor adds no measurable overhead. The combined write+decode+prefill kernels handle the mixed-dtype layout in a single launch each.
The 3 bf16k_* variants exercise the bf16 K-side at the HDIM=128
kernel — the only HDIM=128 bf16-attn model in Atlas's tested set.
Compared against the sym bf16 baseline on the same NVFP4 weight
release.
| dtype | PPL sim | dec_short | pre_2K | pre_8K | pre_16K | dec_after_8K |
|---|---|---|---|---|---|---|
| bf16 (baseline) | 0.2929 | 86.18 | 740.17 | 1186.24 | 1291.79 | 41.97 |
| bf16k_turbo3v | 0.2929 | 84.69 | 709.80 | 1179.45 | 1300.06 | 39.55 |
| bf16k_turbo4v | 0.2929 | 84.29 | 709.78 | 1171.72 | 1294.01 | 40.00 |
| bf16k_turbo2v | 0.3030 | 85.96 | 713.33 | 1181.17 | 1301.00 | 40.34 |
The bf16k_turbo3v and bf16k_turbo4v rows are bit-identical to
the sym bf16 baseline on this prompt — the asym dispatch correctly
preserves K-side precision through the combined kernel. The
bf16k_turbo2v row drops to 0.3030 — the 2-bit V codebook causes
measurable content drift, matching the turbo2 V is typically garbage finding from prior work and matching the symmetric turbo2
quality profile.
Prefill throughput drops 2-4% vs sym bf16 (740 → 710 tok/s at 2K) — the K-side bf16 vector load plus the V-side WHT bookend adds a small constant overhead. Decode-after-8K loses 4-6% (41.97 → 39.55-40.34) for the same reason. Within the ±2% noise budget on every context length above 2K.
(PPL sim absolute value here is lower than Bench F's 0.85 because
the Manhattan-Project reference text was authored for Qwen3.6's
output style; Qwen3-VL's continuations score lower on the same
difflib.SequenceMatcher ratio against the same fixed reference.
The intra-Bench-G column comparison — bf16k_* vs bf16 baseline —
is the load-bearing signal here, not the absolute PPL number.)
The class of bug that initially shipped 8-of-9 asym variants silently falling through to the K-side symmetric kernels (with V mis-sized in the per-side pool, producing garbage attention output) is now blocked at three layers:
- Compile-time exhaustive match —
kernel_modules_for_dtypeincrates/spark-model/src/layers/qwen3_attention/init_kernel_dispatch.rsis exhaustive onKvCacheDtypewith no_arm. A new variant added without a routing fails to compile. - Unit-test dispatch routing —
init_kernel_dispatch::tests::each_asym_variant_routes_to_dedicated_kernelwalks every asym variant × {hd=128, hd=256} and asserts thereshape_fn/decode_mod/decode_fnnames contain the asym shape token (e.g.bf16k_turbo3v). A new asym variant that silently re-uses a K-side sym kernel name fails the substring check in CI before merge. - End-to-end smoke —
tests/test_kv_dtype_smoke.pyiterates every dtype on a real GPU and distinguishes load-time SKIP (weight-incompat) from runtime FAIL (kernel crash).
Run the dispatch tests (no GPU needed):
docker run --rm --entrypoint /bin/bash --gpus all \
-e ATLAS_SKIP_BUILD=1 -e CUDARC_CUDA_VERSION=13000 \
-v $(pwd):/atlas atlas-gb10-tqplus-dev \
-c "cd /atlas && cargo test -p spark-model --tests qwen3_attention::init_kernel_dispatch::"Expected: test result: ok. 4 passed; 0 failed.
The +27.9% nvfp4 dec_after_8K jump above doesn't come from one
heroic change — it's the combined effect of the per-row sparse V skip
(below-threshold rows pay zero V-side bandwidth) and the fp16 LUT
(halves shmem) interacting on the BC=4 batched path. The baseline
nvfp4 decode at long context was effectively spending most of its V
bandwidth on rows that contribute < 1% of the softmax mass after
8K-token context. Skipping them under the exp > 1e-3 gate is the
single largest line-item.
docker run … -e TURBO_INNERQ=512 -e TURBO_INNERQ_STRENGTH=0.5 atlas-gb10-tqplus serve …After 512 calibration tokens (logged at INFO), the post-WHT per-channel
scales are frozen and applied to every subsequent token at ~0 cost (one
fused __nv_bfloat16 mul). Quality on the Manhattan-Project prompt
should match the table above ± noise; deviation indicates a bug.
docker run … -e TQ_PLUS_WEIGHT_ROTATION=1 atlas-gb10-tqplus serve …When active, runtime WHT launches in write_kv_cache.rs are skipped
(160 fewer kernel launches per token at 40 layers × 4 projections). The
attention dot product is preserved because the rotation cancels at
<Q·H, H·K> = <Q, K>.
The primary research source is
TheTom/turboquant_plus
— the umbrella repo Tom Turney uses as a research dumping ground for
the TQ+ work that spans multiple downstream engines (this Atlas port,
the llama.cpp port, the vLLM port, etc.). The ~15 papers in
docs/papers/ and the reference quant/dequant implementations live
there.
The implementation reference for the kernel-level pieces is
TheTom/llama-cpp-turboquant
— the first public llama.cpp fork shipping a complete TurboQuant KV
cache. The CLI surface (--kv-cache-dtype turbo{2,3,4,8}), the seed=42
sign tables vendored as tq_plus_signs.cuh, and the matched-norm L2
trick all trace back to that fork.
Highlights from the turboquant_plus paper set relevant to this port:
asymmetric-kv-compression.md— K bandwidth-critical, V tolerates harder quant; motivates Bf16K+Turbo3V.sparse-v-dequant.md— per-row softmax-gated V skip.inner-q.md—<Q/s, s·K> = <Q, K>identity.layer-aware-v-compression.md(LA-V7) — boundary V layers stay higher precision.triattention-v3.md— long-context eviction policy (NOT ported in this work; substrate exists but no kernel yet).
All of those pieces are AI-generated (per CONTRIBUTING.md's AI-first
policy) by Tom Turney working with Claude over the course of this
integration. The CUDA kernels are hand-tuned by Claude after profiling
on GB10; the Rust dispatch and tests are AI-generated and reviewed.
- Other asym combo kernels (Bf16K+Turbo4V, Bf16K+Turbo2V,
Fp8K+Turbo[234]V) —
prefill_paged_compute_asym.cuhtemplate is in place; each combo is a ~30-line clone of the Bf16K+Turbo3V kernel. - Turbo2 BR=64 prefill — currently uses the BR=32 entry while BR=64 OOB is investigated. BR=64 would be ~15% faster but not blocking.
- TQ4_1S / TQ3_1S weight quantisation — separate from KV cache. Tracked in the TQ+ paper set but explicitly out of scope for this integration.
- TriAttention long-context eviction — substrate exists via
boundary_dtypebut no kernel yet. Tracked undertriattention-v3.mdin the paper set.
See CITATIONS.md at the repo root for the full prior-art chain
(Google TurboQuant paper → TheTom/turboquant_plus umbrella → TheTom/llama-cpp-turboquant engine reference →
this Atlas port).