Repository navigation
[4/6] feat(attention): unify visibility across dense attention backends - #1028
Open
maocheng23 wants to merge 1 commit into
Open
maocheng23 wants to merge 1 commit into
maocheng23 wants to merge 1 commit into
Conversation
maocheng23
requested review from
FlamingoPg,
FrankLeeeee,
shuaills and
sleepcoo
as code owners
October 27, 2026 20:42
This was referenced Oct 27, 2026
Split from #1023. Dense attention now enforces AttentionConfig's causality and sliding window itself, intersected with the algorithm's mask, using logical query/key positions (AttentionContext.query_positions/key_positions) for packed layouts. Queries with no visible key produce zero output on every backend, including after the o_proj bias (previously eager only); individual empty heads are zeroed before projection. Two changes relative to #1023, to keep the default training path as fast as before: - AttentionContext.mask_encodes_visibility: DFlash's per-layer-type masks already encode the same rules, so dense backends no longer rebuild an identical mask (an extra create_block_mask under Flex) in every sliding or causal layer. - Flex requests the LSE only when o_proj has a bias; it already returns zeros for empty rows and heads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maocheng23
force-pushed
the
maocheng/pr1023-4-visibility
branch
from
October 27, 2026 20:45
9c5967f to
4b48be0
Compare
maocheng23
force-pushed
the
maocheng/pr1023-3-residual
branch
from
October 27, 2026 20:45
87551e0 to
33ca045
Compare
yushengsu-thu
added a commit
to yushengsu-thu/SpecForge
that referenced
this pull request
Oct 31, 2026
The five commits before this one carry sgl-project#1025 to sgl-project#1028 (draft layers moved, GQA/MLA attention components with the layer factory, residual kinds, visibility). This commit reconnects the MoE FFN to them: - layers/factory.py: build_ffn takes the layer index and delegates to the MoE package's switch, so moe_preset and ffn_layer_types work again. - layers/decoder.py: DecoderLayer.forward takes moe_token_mask and hands it to an MoELayer as its second argument; dense MLPs keep one argument. - dflash.py: pass the layer index and the mask; DFlash2 already calls _ffn. The one test that used the old build_ffn signature is updated. Temporary until sgl-project#1025 to sgl-project#1028 land on main; then this stack rebases onto them and only this commit is replayed.
yushengsu-thu
added a commit
to yushengsu-thu/SpecForge
that referenced
this pull request
Nov 4, 2026
The five commits before this one carry sgl-project#1025 to sgl-project#1028 (draft layers moved, GQA/MLA attention components with the layer factory, residual kinds, visibility). This commit reconnects the MoE FFN to them: - layers/factory.py: build_ffn takes the layer index and delegates to the MoE package's switch, so moe_preset and ffn_layer_types work again. - layers/decoder.py: DecoderLayer.forward takes moe_token_mask and hands it to an MoELayer as its second argument; dense MLPs keep one argument. - dflash.py: pass the layer index and the mask; DFlash2 already calls _ffn. The one test that used the old build_ffn signature is updated. Temporary until sgl-project#1025 to sgl-project#1028 land on main; then this stack rebases onto them and only this commit is replayed.
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
Make visibility mean the same thing on every dense backend. Each attention layer now enforces its own
AttentionConfig(causality, sliding window) intersected with the algorithm's mask, using logical positions for packed layouts. Queries with no visible key produce zero output everywhere, not only on eager.This is the behavior-changing part of #1023. It was split out so the move, refactor and residual PRs stay bit-exact. It overlaps #970 (draft causality decoupled from SWA layout), and the two should be reconciled.
Modifications (from #1023)
backends/visibility.py:resolve_visibilityintersects causal/window with an explicit mask for eager, SDPA (dense) and Flex (composedmask_mod).prepare_tensor_maskstabilizes rows that are fully masked.AttentionContext.query_positions/key_positions. DFlash passes its anchor-based positions during packed training.o_proj, as eager already did. Empty heads are zeroed before projection.Changes relative to #1023
is_causal=True) rebuilt a mask identical to the one DFlash had already built: an extracreate_block_maskper layer under Flex, or a dense[B,1,Q,K]tensor under SDPA. Measured on CPU SDPA with 2 sliding + 2 full layers, 2 of 4 layers rebuilt, and all rebuilt masks were bit-identical. NowAttentionContext.mask_encodes_visibilitylets an algorithm declare that its mask already encodes the layer's rules, and DFlash sets it.o_projhas a bias. Flex already returns zeros for empty rows and heads; the LSE only exists to stop a bias from reviving them. The default bias-free path therefore keeps its previous kernel call.Accuracy Test
test_visibility.py(from Refactor draft layers and add GR/mHC residuals #1023), plus:is_causal=Truelayers callsresolve_visibility0 times. Forcing the rebuild gives a bit-identical output.return_lseonly with a bias.o_projbias, so the test now excludes those rows from the loss and comparison, the same way training excludes them.tests/test_modelingon CPU: 192 tests, 27 skipped. The only errors are the 4sglang/yunchangimport errors described in [1/6] refactor(draft): move draft layer components under modeling/draft/layers #1025. CUDA-only tests (Flex/Flash) were not run locally and will run in CI.Not measured
No GPU throughput A/B yet. The default DFlash path changes as follows, and it is worth checking on the Qwen3.8 SWA recipe:
mask.any(-1)) per layer.Stack
This is part of a split of #1023 (by @jiapingW) into reviewable layers. Each PR targets the branch of the previous one, and only its own commits show in the diff.
The code is @jiapingW's from #1023 (commits are authored by them). The split adds a parity test, legacy import shims, and two fixes in the visibility PR, each noted in the PR it belongs to.
🤖 Generated with Claude Code