Repository navigation
Conversation
The paged decode consumer layers received the source layer's candidate blocks as a dense position mask and still scored every visible position, masking the non-candidates afterwards, so their indexer cost grew with the context. fp4_index_logits_candidates scores only the positions of the candidate blocks (8-position blocks, -1 padded) and writes -inf to the other visible positions, so every selection is unchanged while the scoring work scales with the candidate count. The dense mask (candidate_block_mask, BlockIds.decode_mask) is no longer built.
ormandj
requested review from
BBuf,
DarkSharpness,
Fridge003,
HaiShaw,
HydraQYH,
Qiaolin-Yu,
celve,
hebiao064,
ispobock,
merrymercy and
yuan-luo
as code owners
October 9, 2026 17:37
12 of 54 tasks
|
Hi @ormandj, thanks for the work! Just wanted to flag that candidate-only paged FP4 decode scoring is already part of my ongoing PR #40860. Both implementations reuse _fp4_index_logits_tile with candidate block addressing, so there is substantial overlap. |
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
In the dense-blocks candidate scheme, a source layer publishes up to 2,048 blocks of 8 compressed positions per decode row, and consumer layers select their top-k only inside those blocks. On the paged decode path (SM90 today; SM120 with #42371), the source turns the block IDs into a boolean mask over the full CUDA-graph capacity (
candidate_block_mask), and every consumer still runsfp4_index_logits_pagedover every tile of the visible context, with non-candidate positions masked out. Consumer cost therefore grows with context, even though at most 16,384 positions can be selected.Modifications
fp4_index_logits_candidates(dsv4/fp4_indexer.py) fills the visible range with -inf, then scores only the candidate blocks with the same_fp4_index_logits_tile. Tiles whose blocks are all padding or past the visible length are skipped. Visible scores match the masked scan.decode_scorestakescandidate_blocksinstead ofcandidate_mask; the paged consumer passes the published block IDs.BlockIds.decode_maskandcandidate_block_maskare removed (the mask moves into the test as the reference). The non-paged path is unchanged.Accuracy Tests
test_fp4_candidate_logits_match_masked_scanreplays a CUDA graph with lengths (including 0 and tile boundaries), queries and block IDs changing between replays, and asserts that the candidate scorer's visible scores are bitwise equal to the maskedfp4_index_logits_paged(random BF16 queries and weights, 32 and 64 heads, ratios 1 and 2, padded block lists, one row without candidates).test_hopper_indexer_backends_replaychecks that the source and full top-k use the paged scorer and the consumer uses the candidate scorer, and still checks the selections against the torch reference.On one RTX PRO 6000 (SM120), with this PR applied to a tree that also carries #42371 and #42861,
python -m pytest test/registered/kernels/ops/attention/test_fp4_indexer.py: 104 passed and 36 skipped (test_fp4_logits_visibility_boundariescases). The passes include the candidate cases[6-32-1-193-None],[6-64-2-8193-None],[4-64-1-32769-None]and[64-64-1-32769-1048580], andtest_paged_indexer_backends_replayfor ratios 1 and 2, which is #42371's SM120-enabled form oftest_hopper_indexer_backends_replay. On this PR alone,test_hopper_indexer_backends_replayis gated to capability 9 and does not run on SM120. Hopper was not tested.Speed Tests and Profiling
Mask construction plus one scorer call on one RTX PRO 6000 (SM120). Inputs: 64 heads, page size 64, capacity 262,144 positions, scorer
ratio=1, dyadic BF16 queries and weights, random FP4 key bytes with E8M0 scales near 1, one request on shuffled pages. Rowrseescontext - rpositions and getsmin(2048, ceil(context / 8))distinct random candidate blocks. Each variant is captured as 20 calls in one CUDA graph and timed over 10 replays after a warm-up replay; the table reports time per call. Visible scores were equal in every case."Mask + masked scan" is
candidate_block_maskplus maskedfp4_index_logits_paged; "Candidates" isfp4_index_logits_candidates. The mask was built once per source layer and shared by its consumers, so the per-consumer saving is smaller than this table shows.Checklist
Developed with AI assistance.
CI States
Latest PR Test (Base): ❌ Run #37967581067
Latest PR Test (Extra): ❌ Run #37967580523
Latest PR Test (AMD ROCm 10): ❌ Run #37967581058