Repository navigation
Conversation
…he contiguous kernels' bits hpattn_paged_kernel and hpattn8_paged_kernel<256, 8, 2, 2> read the qwen3_5 pool's pages (qwen35.cuh kv_row: a page holds each key head's ptok rows in a run, as a cache of cap ptok does). They are hpattn_kernel and hpattn8_kernel with CAP = ptok and a page term on each row's address: the same 64-key tiles in the same order, only the global address a 16-byte chunk is staged from moves, so their outputs are the contiguous kernels' bytes. prefill_attention_rows.cuh's head-major address takes PT[row / CAP] * PS (bytes for e4m3, whose fp32 scales sit at PS / 4 floats a page), the page id read once a 32-key staging item and per row only where an item straddles a page; with PT the constexpr null of the existing kernels it folds away: every existing function's SASS is unchanged on sm_80/86/89/120/121, every other fatbin byte-identical. Kernel contract: hpattn_kernel and hpattn8_kernel at the 27B's 24/4 heads against float64 (attention_ref's bound, gates 1-4), and the paged twins at pages of 256 and 48 positions, shuffled in an arena with spare junk pages, each replacing its contiguous kernel bit for bit at 14 shapes up to 4096-row chunks; control: a table whose first page id is a later page's. Launch records for all four, with nvcc 13.2 overrides.
With TF_QWEN_KV_PAGES on a stream (every stream under TF_QWEN_KV_PAGES_ALL or TF_QWEN_KV_SHARE), a prompt chunk went through the scalar paged decode partials and their merge, about twice the contiguous chunk's time. A one-part prompt chunk now runs hpattn_paged_kernel (or hpattn8_paged_kernel for --kv-cache fp8) over its pages: the launch of the contiguous chunk at cap = the page's positions, from page 0 of the arena, with the stream's table. Its bytes are the contiguous chunk's, so a stream's outputs no longer depend on whether it holds pages. Windows of several parts keep the paged partials. Every prefill's first-row logits on pages (27B bf16 and fp8, 35B-A3B; pages of 256 and 48; with and without drafts and the prefix cache) equal main's contiguous ones. TTFT on pages is within noise of contiguous at 2k, 8k, 32k and a warm turn (27B 32k 27.8/27.5 s vs 29.4/27.9 s; 35B 6.61/6.56/6.62 s vs 6.42/6.62/6.80 s).
Contributor
Author
|
Closing: 0843339 (#1373) gives paged prompt chunks the tensor-core tiles over the page table (and the decode tiles too), and |
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.
What
With
TF_QWEN_KV_PAGESon a stream (every stream underTF_QWEN_KV_PAGES_ALLorTF_QWEN_KV_SHARE), a Qwen3.5prompt chunk currently goes through the scalar paged decode partials plus their merge. That costs about 2x TTFT
(the 27B measurement on #1357's original head a1804ab: cold 8k 7.3 s contiguous vs 15.7 s paged; warm turn 0.75 vs 2.2 s). This PR adds paged twins of the
contiguous prompt kernels and routes one-part paged prompt chunks to them.
hpattn_paged_kernel/hpattn8_paged_kernel<256, 8, 2, 2>(prefill_attention.cu):hpattn_kernel/hpattn8_kernelwithCAP = ptokplus a page table. A qwen3_5 page stores each key head'sptokrowsconsecutively (qwen35.cuh
kv_row), which matches a contiguous cache ofcap = ptok. Only the global addresseach 16-byte chunk is staged from changes:
PT[row / CAP] * PS, with the page id looked up once per 32-keystaging item and a per-row lookup only where an item straddles a page. The kernel folds the same 64-key tiles in
the same order, so paged == contiguous, bit for bit.
prefill_attention_rows.cuh: the head-major address takes the page term. For the existing kernelsPTis theconstexpr null, so the term folds away. Every existing function's SASS is unchanged on
sm_80/86/89/120/121; 0 changed functions across all 97 fatbins (sm_121); 2 added.
cuda_prompt.runlaunches the paged twin when the stream's Seg has a table.cuda_forwardtakes theprompt branch for a one-part paged prompt chunk ahead of the scalar paged partials. Windows of several parts
(verify) keep the paged partials.
No family changes its bytes. A paged Qwen stream now produces exactly the contiguous stream's prefill outputs,
where today it does not.
Kernel contract
zig/tests/cuda/contract_prompt_pages.zig:hpattn_kernel/hpattn8_kernelat the 27B's 24/4 heads against float64 (attention_refbound,gates 1-4);
replacesits contiguous kernel bit for bit at 14 shapes, including 4096-row chunks and resumes at 2048/4096;Launch records are in
prompt_pages_records.zig(nvcc 13.0, plus 13.2 overrides).Gates (server, greedy, first-row logits hash of every prefill + reply text)
control shows this predates the PR: main with PAGES_ALL on the same short prompts gives the same divergent text.
On main, paged prefill logits also differ for those prompts; this PR makes them equal.
Speed (TTFT s, fresh servers alternating, 2+2 for 27B and 3+3 for 35B; texts and logits identical across all arms and rounds)
Paged is within noise of contiguous at every length (the 27B main round 0 is the slower cold first start). For
scale: on the scalar paged partials, a1804ab's own 27B measurement (its prompt set) had cold 8k at 15.7 s paged
vs 7.3 s contiguous, and a warm turn at 2.2 vs 0.75 s.
Dependencies / notes
qwen3_5/cuda_forward.zigas cuda qwen3_5: a paged prompt chunk's attention goes through most_verify rows at a time #1355 (which slices paged chunks over 128 rows into the partial buffers' size): whichever lands second takes one small conflict there. With this PR, a one-part paged prompt chunk no longer reaches cuda qwen3_5: a paged prompt chunk's attention goes through most_verify rows at a time #1355's path; cuda qwen3_5: a paged prompt chunk's attention goes through most_verify rows at a time #1355's slicing remains needed for multi-part paged windows over 128 rows, which do not occur today.TF_QWEN_KV_SHARE) was held for; the SHARE rows above were measured with cuda qwen3_5: the prompt cache keeps KV pages on the device (TF_QWEN_KV_SHARE, #1156) #1357 stacked on this PR.