fix(ROCM): AttnQkNormRopeGate output-dtype dispatch -- the 0.8B GDN forward divergence root-caused and fixed (RED anchor turns GREEN) - #570
Conversation
c5b0b11 to
ab41b73
Compare
Current-main rebase and fresh reviewRebased from
|
…lden lane in the Qwen3-0.6B near-tie gate Issue mudler#41 M4 milestone. The oracle is upstream vLLM AT THE PIN (555967922, runtime 0.23.1rc1.dev1511+g555967922 -- verified == the parity-pin block) built from source as a ROCm wheel for gfx1100 in rocm/vllm-dev:base and committed as the image vllm-rocm-oracle:555967922-gfx1100 (recipe: .agents/specs/rocm-m4-oracle.md). Gate result on this box (4x RX 7900 XTX, ROCm 7.14, enforce_eager, batch=1, flock ~/gpu.lock): oracle K=10 per-prompt greedy deterministic in every cell; our ROCm engine 16/16 prompts PASS -- 11/16 strict token-exact vs base greedy, 5/16 near-tie band, max teacher-forced gap 0.125 nats, 0 forward-divergent, 125/125 assertions, backend proof all 8 Qwen3-dense ops selections>0 and declines==0 on device 5. The p0 France/Italy flip is a literal 0.0000-nat tie in the oracle's own logits (the Metal M3b signature, reproduced on ROCm). Change shape: the parity gate's Metal/Tenstorrent device-golden lane gains the kROCM arm (identical anchor+band logic, ROCm's own oracle-backed golden pair); dgx base goldens byte-untouched; the *_rocm goldens are additive. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: pi:kimi-k3 [pi]
…he 0.8B GDN forward divergence, root-caused and fixed Issue mudler#41. The ROCm dispatcher for the fused full-attention preamble keyed its template on the SOURCE dtype (qgate.dtype) instead of the OUTPUT dtype like the CUDA lane (LaunchAttnPreambleOut switches on q_out.dtype). The 0.8B bf16 model runs bf16 QKV-projection output + f32 q/k/gate outs (the f32-attention path; no FA-2 on ROCm), which the src-keyed dispatch mis-launched as all-bf16 -- writing bf16 bits through the f32 out pointers. Evidence chain (gfx1100, flock): CPU==pinned-oracle token-exact / ROCm diverges at tok0; VT_DUMP_ACT per-layer residual dumps: layers 0-2 clean (<=9.6e-3), layer 3 (first full-attn) 2.1e-1; sub-stage dumps: block_out 4.4e-1 with post_input_norm clean; VT_DUMP_ATTN op dumps: fa0_q rms-rel 1.196 with qkv/gate clean; VT_ROCM_ATTN_CPU_REF=1 unchanged. Fix: dispatch on q_out.dtype; bf16-out requires bf16-src (VT_CHECK). Teeth: the cross-device AttnQkNormRopeGate case gains the bf16-src -> f32-out combo at the real 0.8B dims (Hq=8, Hkv=2, Dh=256, rot=64); mutation-proven (fails with the fix reverted, passes with it). Gates on this branch (gfx1100, flock ~/gpu.lock): test_backend_cross_device 19/19 (346 assertions, incl. the new combo); test_qwen3_paged_engine 16/16 unchanged; e2e 0.8B 'The capital of France is' -> ' Paris.\nThe capital of France is' == pinned oracle == our CPU. The M4 0.8B gate with the re-derived GREEN goldens lands in the stacked sibling on row/ROCM-M4-GDN-GATE; full HIP ctest zero-delta vs base measured there. Also: three pre-existing hipcc/clang-only build breaks that block ANY full HIP build on this toolchain: same-line double CAPTURE in test_qwen3_5_gdn_spec_routing.cpp and test_ops_quant_repack.cpp, and -Wunused-const-variable on kGdnLayers (uses compile out on HIP). Debug instrumentation env-gated and off by default (VT_DUMP_ACT / VT_DUMP_ACT_SUB / VT_DUMP_ATTN; deepseek_v4 VT_DUMP_ACT precedent; env-doc-allowlist updated). FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: pi:kimi-k3 [pi]
ab41b73 to
fd83663
Compare
Final integration cutoffFinal head:
|
… gate (#559) ## M4 for Qwen3.5-0.8B (GDN) — the oracle-backed gate, landed green-shaped (issue #41) Stacked: #549 (0.6B lane + oracle) ← **the dispatch fix** (#570) ← this gate. The fix lands *below* the gate, so every commit in the stack is individually green on the gate host and the committed goldens are ones the tree can actually reproduce. ### Gate `test_qwen35_paged_engine.cpp` — the GDN sibling of the Qwen3-dense SACRED gate: standard 16-prompt battery through the full paged engine, hard anchor + ≤0.5-nat near-tie band, backend proof over the 15-op GDN set. Goldens captured from the pinned vLLM-ROCm oracle on this box (K=10 per-prompt, **deterministic in every cell**) with `manifest.json` recording the oracle identity; the checkpoint resolves via `parity::HfSnapshot` at the pinned HF revision `2fc06364` (check-snapshot-pins clean). **Verdict: 16/16 PASS** (15/16 strict token-exact vs the oracle, 1/16 near-tie band, max gap 0.125 nats, 0 forward-divergent). ### Review-sweep rework (all three findings accepted) 1. **CI-red manifest fixed**: `qwen35_0_8b_greedy` is in `PendingRunnerOps()` (the `qwen36_gguf_greedy` precedent) — the manifest itself stays; its oracle identity is the point. 2. **Fail-safe by device**: the gate exits 77 (CTest Skipped) on any non-ROCm device and when the pinned checkpoint is absent — never a false green, never a foreign engine compared against ROCm-derived goldens. 3. **Green-shaped landing**: the committed goldens are the FIXED engine's oracle-re-derived pair. The pre-fix capture (13/16 forward-divergent; first-token divergences on 6 prompts at 0.375–1.062 nats, 5 of 6 over band) is kept as evidence in the spec + parity ledger, not as goldens no code can pass. The anchor-drift REQUIRE now reads "REGRESSION SUSPECTED — bisect first"; golden re-derivation is the last step of a justified re-capture, not the response to a failure. ### Prose corrections from review First-divergence maximum is 1.062 nats (not 1.188), 5 of the 6 token-0 divergences are over the band (not all), and the headline gap is at the first over-band position rather than a post-divergence maximum. ## In-flow gate repair Issue #1222 found three missing-artifact paths that returned normally and let doctest report false success. The gate now routes absent greedy, anchor, and gap artifacts through exit 77. A no-GPU subprocess regression drives the real executable and asserts `77/77/77`; its complete-artifact control requires hard sentinel exit 86 so probe mode can never bypass snapshot/model/device checks as zero-assertion success. Bootstrap writes its token IDs and then exits skipped until correctness artifacts exist. Malformed present arrays remain hard failures. Fixes #1222. ## Current-main integration cutoff (2026-08-18) Rebased from `5b31bc30349d527ef0b4c1c8fcd7c86749b4cfa3` to `4673a35dd47087cae3f6f9808e4fcf64667bcbcf` on recorded current-main cutoff `65d6cdaed3e20e9bc70b4f9374fccafefefa7bd0`. Exact six-commit replay of #549 → #570 → the green 0.8B gate → the three #1222 spec/repair commits. Fresh cutoff-head builds, focused gates, full repository preflight, and independent mutation review all pass. ## Landing note (maintainer) This branch is the tip of the 0.6B/0.8B ROCm stack and carries six commits: the #549 M4 oracle and 0.6B gate lane, the #570 `AttnQkNormRopeGate` output-dtype dispatch fix, the green 0.8B GDN gate, and the three #1222 gate repairs. Landing it lands that whole stack, so #549 and #570 are closed against this merge rather than squashed separately. Merging the tip is deliberate: squash-merging a stack in order rewrites each ancestor's history and destroys the merge base of the branches above it. `agent-record` is red on the pull request and the merge result is green. The branch predates the #1229 gate-commands repair now on `main`, so it ran the 41-test version of `tests/scripts/test_check_gate_commands.py` against its own tree. The actual merge was constructed locally and gated: 42 tests OK, and `check-agent-record`, `check-doc-checkpoint`, `check-issue-index-append-only` and `check-readme-structure` all pass on the merged tree. `windows-msvc-cpu` and `windows-msvc-vulkan` are red as they are on every pull request here and carry no verdict. The remaining 17 gates passed. The ROCm correctness evidence is the contributor's and was not re-run by the maintainer: it needs the gfx1100 board, which this session did not hold. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: pi:kimi-k3 [pi] Assisted-by: codex:gpt-5.6-sol [codex] Assisted-by: pi:gpt-5.6-sol [pi]
|
Landed via #559 as #559 is the tip of this stack and carried this branch's commit The tip was merged rather than each branch in turn because this repository is squash-only, and squash-merging a stack in order rewrites each ancestor and destroys the merge base of the branches above it. Authorship is preserved on the landed commit. This one deserves a note: the evidence chain here, CPU backend matching the pinned oracle token-for-token, per-layer residual dumps localising the ignition to layer 3, then sub-stage and op dumps narrowing to |
fix(ROCM): AttnQkNormRopeGate dispatch keyed on the OUTPUT dtype — the 0.8B GDN forward divergence, root-caused and fixed (issue #41)
Restructured after review: this PR now carries ONLY the kernel fix + its teeth + the debug instrumentation, and lands BELOW the 0.8B gate (#559) so every commit is individually green on the gate host.
Root cause
The ROCm dispatcher for the fused full-attention preamble templated the kernel on the source dtype (
qgate.dtype) where the CUDA lane (LaunchAttnPreambleOut) switches on the output dtype (q_out.dtype). The 0.8B bf16 model runs bf16 QKV-projection output + f32 q/k/gate outs (the f32-attention path; no FA-2 on ROCm) — silently mis-launched as all-bf16, writing bf16 bits through f32 out pointers.Evidence chain (gfx1100, GPU-locked)
VT_DUMP_ACT): layers 0–2 clean (≤9.6e-3 rms-rel), layer 3 (first full-attn) ignites to 2.1e-1VT_DUMP_ACT_SUB):block_out4.4e-1 withpost_input_normclean → inside FullAttnBlockPagedVT_DUMP_ATTN):fa0_qrms-rel 1.196 withfa0_qkv/fa0_gateclean → the preamble's q/k pathVT_ROCM_ATTN_CPU_REF=1unchanged → attention core exoneratedFix + teeth
Dispatch on
q_out.dtype;VT_CHECKbf16-out requires bf16-src. The cross-device case gains the bf16-src → f32-out combo at the real 0.8B dims (Hq=8, Hkv=2, Dh=256, rot=64) — mutation-proven: fails with the fix reverted, passes with it.Gates (gfx1100, flock)
test_backend_cross_device19/19 (346 assertions)test_qwen3_paged_engine16/16 unchangedThe capital of France is→Paris.\nThe capital of France is== pinned oracle == our CPUAlso in this PR: three pre-existing hipcc/clang-only build breaks that blocked any full HIP build (same-line double
CAPTURE×2;-Wunused-const-variableon a CUDA-gated constant), and the env-gated dump instrumentation that found the bug (VT_DUMP_ACT/VT_DUMP_ACT_SUB/VT_DUMP_ATTN, off by default, allowlisted).Current-main integration cutoff (2026-08-18)
Rebased from
053a18a42346e2610a8b56418ebd387c5e74a5c6tofd836638d7a92bdbd755a7b73b9493f1ff9f6a0don recorded current-main cutoff65d6cdaed3e20e9bc70b4f9374fccafefefa7bd0. Exact output-dtype-fix commit replay. Fresh cutoff-head builds, focused gates, full repository preflight, and independent mutation review all pass.FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: pi:kimi-k3 [pi]
Assisted-by: codex:gpt-5.6-sol [codex]
Assisted-by: pi:gpt-5.6-sol [pi]