Repository navigation
[Fix] deterministic: Keep the GDN output tile fixed for varlen prefill - #44194
Open
aarnetalman wants to merge 2 commits into
Open
aarnetalman wants to merge 2 commits into
aarnetalman wants to merge 2 commits into
Conversation
chunk_fwd_o picks its chunk tile from T, which for varlen input is the total token count of the whole batch. A short prompt prefilled alone gets a 16-token tile, and the same prompt prefilled with batchmates a 32- or 64-token one, so its Gated DeltaNet output is reduced differently and the last bits change. That makes hybrid GDN models (Qwen3.5 and later) batch- variant for short prompts under --enable-deterministic-inference; every other stage of the GDN prefill is batch-invariant. Use the full chunk size for varlen input. Fixed-length batches keep the smaller tile, since there T is the sequence length. Signed-off-by: Aarne Talman <aarne.talman@amd.com>
This was referenced Oct 14, 2026
rkarhila-amd
approved these changes
Oct 14, 2026
rkarhila-amd
left a comment
There was a problem hiding this comment.
It's a tiny but necessary change. Again more test code than code changes.
aarnetalman
marked this pull request as ready for review
October 14, 2026 19:47
aarnetalman
requested review from
hebiao064,
yizhang2077 and
yuan-luo
as code owners
October 14, 2026 19:47
# Conflicts: # python/sglang/kernels/ops/attention/fla/chunk_o.py
4 of 5 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Hybrid Gated DeltaNet (GDN) models (Qwen3-Next, Qwen3.5 and later) are not batch-invariant for short prompts under
--enable-deterministic-inference: the same prompt gives different log-probabilities depending on what it is batched with.The cause is one line in
chunk_fwd_o, the last kernel of the GDN chunked prefill:For varlen input (
cu_seqlens),Tis the token count of the whole batch, not of one sequence. A 9-token prompt prefilled alone gets a 16-token tile; the same prompt prefilled together with others gets a 32- or 64-token tile. The output is reduced over a different tile, so the last bits change. Every other stage of the GDN prefill (L2 norm, gate cumsum, the intra-chunk solve, the chunk states) gave bitwise-identical results in our tests.We found it on MI350X with Qwen3.8-27B. The bitwise check below sends the same short prompt 1 to 50 times in one request and compares every response with the batch-size-1 one: token IDs were always identical, but log-probabilities matched in only 33-48 of 1,275 responses at TP2 (triton attention, AITER off; 8 runs), and 50-51 of 1,275 at TP1 with AITER on. The first token's log-probability already differs. Disabling the radix cache, CUDA graphs, or the overlap scheduler, or forcing RCCL for the all-reduce, did not change that.
The same Triton kernels run on NVIDIA in deterministic mode (FlashInfer GDN prefill is refused there), so this is not specific to ROCm.
Modifications
chunk_fwd_o: use the full chunk size (64) as the tile for varlen input. Fixed-length batches keep the smaller tile, since thereTis the sequence length.test_chunk_gated_delta_rule.py: new casetest_short_sequence_output_independent_of_batchmates: sequences of 10-16 tokens (Qwen3.8's head layout: 16 query/key heads, 48 value heads, 128 wide), 6 seeds each, must give bitwise the same output alone and packed with a copy.Accuracy Tests
MI350X,
rocm/sgl-dev:v0.5.21-rocm724-mi35x-20261012with this change applied.Unit test,
python3 -m pytest test/registered/attention/test_chunk_gated_delta_rule.py: before, the new case fails (1 failed, 30 passed); after, 31 passed.Kernel level: for 1,896 random sequences (lengths 2-80, 12 seeds, Qwen3.8-27B head counts at TP1 and TP2), each sequence alone vs packed with a copy, every stage of
chunk_gated_delta_rulecompared bitwise. Before: onlychunk_fwd_odiffers, in 26 cases, all 10-16 tokens long. After: 0 cases.End to end, Qwen3.8-27B BF16,
--attention-backend triton --linear-attn-prefill-backend triton --linear-attn-decode-backend triton --enable-deterministic-inference, #43788, #34543 and #44076 applied. Bitwise check: 1,275 greedy responses (thesingleprompt sent 1 to 50 times per request, 100 tokens each), token IDs / log-probabilities identical to batch size 1:SGLANG_USE_AITERpython3 -m sglang.test.test_deterministicmodessingle,prefix,prefix --return-logprobandradix_cache(50 trials) return one output per group in all four configurations after the change; the bitwise result repeated on TP1 (AITER off and on) and TP2 (AITER off). These runs follow the existing deterministic end-to-end tests (TestDeterministicBase, e.g.test_qwen35_deterministic.py), which are CUDA-only and compare decoded text only; here log-probabilities and the bitwise check are compared as well. Happy to add an AMD end-to-end test if wanted.GSM8K (all 1,319 questions, temperature 0,
sgl-eval0.1.2), Qwen3.8-27B: 95.91% in normal mode (--attention-backend aiter, without these changes), 96.06% with--enable-deterministic-inferenceand this change together with #43788, #34543, #44076 and #44195.Speed Tests and Profiling
Only prefill batches with at most 32 tokens in total take a different tile; larger ones are unchanged (the tile was already 64). Time of a whole
chunk_gated_delta_rulecall for such batches (Qwen3.8-27B shapes,triton.testing.do_bench, median, before/after alternated twice):The unaffected batches moved by the same 2-4%, so that is run-to-run variation; at these sizes the call is bound by kernel launches.
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ❌ Run #40674924130
Latest PR Test (Extra): ❌ Run #40674924228
Latest PR Test (AMD ROCm 10): ❌ Run #40674923828