Repository navigation
lm_head: one-pass BF16 batch2 LM head on every target (stacked on #153; GB10 Flash-Next MTP verify) - #159
Conversation
A BF16 LM head at num_tokens == 2 fell back to two dense_gemv calls, reading the whole weight once per verify token. Qwen3.8-Flash-Next ships its [248320, 2560] LM head BF16, so every MTP verify step read 1.27 GB twice: 2 x 5.87 ms of a 111 ms step on gfx1151 (ATLAS_TRACE_LAUNCH_SYNC, winbox, 2026-10-02). The FP8 and NVFP4 branches already had batch2 arms. Route it to dense_gemv_bf16_batch2 on HIP only. The strix-hip kernel is bit-identical to two dense_gemv_bf16 calls: same 32-lane walk per row and the same shuffle reduction, with the second token as an independent accumulator. The gb10/strix (NVIDIA) builds use 64 lanes per row plus a shared-memory reduction, which reorders the sum, so the handle stays 0 there and the fallback runs unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…A/B attribution Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The HIP-only gate rested on a wrong premise: the gb10/strix (NVIDIA) dense_gemv_bf16 also walks 64 lanes per row with the same smem pair-sum as its batch2 sibling (the '// 32' comment in dense_gemv_bf16.cu is stale), so the pair is bit-identical there too. Flash-Next's BF16 LM head was read twice per MTP verify step on GB10 as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
GB10 result (reiner job 664): PASS. M = main Why util 0.90 / seq 8192: with MTP pools Flash-Next does not fit at 0.88 (job 663: KV exhausted / no KV at boot), and MTP verify only runs below the 2,051-token QSA bound anyway.
Ready for review after #153 merges (this is stacked on it). Its own diff is |
Status (2026-10-06): GB10 gate passed; waiting only on #153 (stacked).
To unblock: merge #153, rebase so only Owner: Claude. |
|
Merged after the GB10 gate in train #305 (sparky; this PR's head 25cd5b5 merged unchanged on main 8c2b672, compared against an A0 binary of main at that same base). Byte-identical controls (
Benchmarks, FP4-Local, train vs main:
Earlier standalone gate (job 59, on this PR's merge ref): control identical, BFCL 87.54 / 85.94, agentic 47/50. No speed claim: I didn't run a K=2 lm_head microbench on GB10. |
Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Stacked on #153. Until #153 merges, the diff includes it; afterwards, only the last commit (
25cd5b55d) remains.What
#153 gated the one-pass BF16 batch2 LM head to HIP, on the premise that the NVIDIA
dense_gemv_bf16_batch2reorders the sum. That premise was wrong. Inkernels/gb10/common/(andkernels/strix/common/),dense_gemv_bf16also walks 64 lanes per row (BLOCK_SIZE 256 / N_PER_BLOCK 4; the// 32comment on that line is stale), with the same warp shuffle + smem pair-sum as its batch2 sibling. A structural diff shows batch2 only adds a second accumulator. So the pair is bit-identical on NVIDIA too, and this commit drops the HIP gate.Why
Qwen3.8-Flash-Next ships a BF16
[248320, 2560]LM head, and its MTP K=2 verify reads it twice per step on GB10 just as it did on gfx1151. On winbox, #153 measured ~+6% decode, byte-identical.Checks
cargo test -p spark-model --lib: 914/914 pass. clippy and fmt are clean.🤖 Generated with Claude Code