Repository navigation
qwen CUDA: paged KV streams take the tensor-core attention, so a paged batch's replies equal a whole window's - #1373
BobClawblaw wants to merge 1 commit into
Conversation
…d batch's replies equal a whole window's With TF_QWEN_KV_PAGES, a batch holding a paged stream ran every row's attention through the partial-only kernels, the prompt chunks included, while whole windows take the tensor-core tiles; the two round differently, so a stream's reply depended on whether a page table was in play. The tiles (Bf16Tiles, Fp8Tiles) now take the key head and read positions through the stream's page table when it has one, the prompt kernels take (PT, PS, PTOK) and read pages in head-major mode, and the paged branch of the forward pass is gone. The engine no longer holds the partial-only kernels' handles; the qwen-pages check runs the tensor-core decode kernels and the prompt kernel on pages against contiguous as well. The four tensor-core launches' nvcc 13.3 receipts (measurements/qwen_lanes_133.zig) are re-measured from five-SM fatbins: the page-or-slab addressing costs registers (tf_q35_attn_rows and attn_rows8 at 255 on every SM, attn_partial 204 below sm_120, attn_partial8 206 to 228), none of them spilling.
|
Tested on a second architecture: RTX 4080 SUPER (sm_89, 16 GB), Windows 11, CUDA 13.3, built with #1344 reproduces on sm_89, and this PR fixes it. The test runs
Speed (9B, Suites:
|
|
Also checked on an RTX 4090 (24 GB, Served, Qwen3.8-27B MLX 4-bit + DFlash2,
Before this change, the same harness with
|
Follows #1344. With
TF_QWEN_KV_PAGES, any batch holding a paged stream ran every row's attention through thepartial-only kernels (
tf_q35_attn_partial_paged+ merge), the prompt chunks included, while whole windows take thetensor-core tiles (
tf_q35_attn_partial/attn_rows,hpattn_kernel). The two paths round differently, so a stream'sreply depended on whether a page table was in play: beside other streams on pages it differed from its solo reply
(6-8 of 12 on an RTX 5090).
What changes
qwen35_attn_tc.cuh:Bf16TilesandFp8Tilestake the key head and address rows by cache position; withsg.ptset they read through the stream's page table (
TfQ35PageRun, the layoutqwen35.cu/qwen35_kv8.cuwrite), elsethe slab as before.
attn_oneandattn_rowspass positions, not slab rows.prefill_attention_rows.cuh: the head-major mode (HM) reads pages whenPTis set (PTOKrows a head,PSapart, in the cache's units);
hpattn_kernel/hpattn8_kerneltake(PT, PS, PTOK), andcuda_prompt.zigpassesa paged stream's table with the layer's block of a page as the base (new mangled symbols pinned there).
cuda_forward.zig: theif (shape.paged)branch is gone; paged and whole batches take the same launches.cuda_attention.zigkeepshasPages(the graph key) and loses the partial-only launcher and its fake-engine test.measurements/qwen_lanes_133.zig: the four tensor-core launches' nvcc 13.3 receipts, re-measured from five-SMfatbins (
zig build fatbins kernel-contract-fatbins -Dsm=80,86,89,120,121, the limits runner's RECORD lines). Thepage-or-slab addressing costs registers:
tf_q35_attn_rows/attn_rows8255 on every SM (from 254/246 and 255/245),tf_q35_attn_partial204 below sm_120 (168 there, unchanged),attn_partial8218/218/228/206/206 (from199/199/207/197/197);
cuobjdump --dump-resource-usageshows no stack or local memory for any of them on any SM.The 13.0 base records of these launches (
cuda_lane_pending.zig, used below nvcc 13.2) are from before this change;no nvcc 13.0 here to re-measure them.
contract_qwen_pages.zigalso runs the tensor-core decode kernels and the prompt kernel on pages against contiguous(bytes equal, the contiguous results within the float64 bound, the swapped-table control red for them too).
Checked on an RTX 5090 (CUDA 13.3, driver 615), Qwen3.8-27B MLX 4-bit + DFlash2, fp8 caches, int8 prompts, main
at 31a864f plus this change, the suite's 12 snapshot prompts, replies compared by token ids:
TF_QWEN_KV_PAGES=256 TF_QWEN_KV_PAGES_ALL=1against the same build's whole window: 12/12identical (before the change, on 1.1.5: 7/12 differed; the earlier diagnosis in Qwen3.8-27B CUDA: with TF_QWEN_KV_PAGES a batch takes the partial-only attention path, so its replies differ from the same replies alone (1.1.5, RTX 5090) #1344)
TF_QWEN_KV_PAGES=256): together == alone 12/12 (1.1.5: 6-8/12)tf-cuda-test qwen-pages: bf16 and fp8 pass at every case (paged == contiguous for the partial, tensor-core and prompt rows; rope stores and keep; the swapped-table and planted-row controls red)zig build kernel-contract -Dsm=120: 340 kernels pass gates 1-4, 94 controls red as planted, 5 known findings and 161 limit problems, the same set as main's at 31a864f on this card (the awaiting launches and 13.3's live register counts against older records); the four re-measured launches readrecord currentone stream, the suite's prompts):
(the unpaged path takes the same launches, the tiles now choosing slab or page addressing; the harness's structured and tool cases were not run against
this build, which has no grammar library beside it)
TF_QWEN_KV_PAGES=256): 277.4/536.3/351.5/336.1 against 1.1.5's 274.5/538.6/352.4/336.8;the 12 prompts together == alone 12/12, drafted == plain 12/12; 30,744 MiB idle
Required checks (
zig build test,test-kernel-contract,test-golden,test-server-security test-pull-security,fuzz-cortheon,zig fmt --check build.zig zig, the lean check): all pass; lean 0 newRebased onto 40c6406 before the push (no overlap with the commits in between); the required checks and
tf-cuda-test qwen-pageswere run again on the rebased tree and pass. The card measurements above are from the change on 31a864f.