Repository navigation
Conversation
…e previous DMA from it Stager::work waited for a buffer's DMA only from the generation's kRing-th job on (j >= kRing); a generation's first kRing jobs wrote their buffers straight away. The previous generation's last DMAs from those buffers are only known to be done where something else waits for them: the routing sync before a staged layer's start(), or the sync at the end of a chunk with an MTP drafter or stages. A stream_all chunk that ends without one (no --mtp), or a ring entry the routing skipped (its copy is never waited for), leaves a window where the next chunk's first jobs overwrite a pinned buffer a DMA may still read. The event is now waited for on every job; an event never recorded, or already complete, returns at once. IQ2_XS with --mmap-experts --resident-budget-gib 16 (12,144 of 48,668 streamed experts through the stager): the same tokens on a 32K prompt, prefill 6,491 vs 6,546 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio
e15988f to
c55854c
Compare
|
Rebased on 0.1.32 (c499bd1), no conflicts. Checked on 0.1.32: IQ2_XS (ISTA), RTX 5090, a fixed 🤖 Generated with Claude Code |
|
Data point for a setup that really streams through the stager: on this 64 GB Windows 11 box |
|
@BlueKingMuch thank you for checking this on a setup that really streams through the stager. 🤖 Generated with Claude Code |
…iko1221#374 Niko1221#363 Niko1221#407 Niko1221#413 onto 0.1.35 One dpct run of upstream main + the seven PRs, 3-way merged into the files they touch (sycl/tools/merge_upstream.py); their header changes are forked into sycl/include until upstream merges them. - Niko1221#385 stager waits for a buffer's previous DMA on every job (port: polled seq) - Niko1221#463 decode waits for an adaptive swap before reading residency - Niko1221#453 drafter's batched K/V on the KV-streaming ring - Niko1221#374 first chunk's PLE rows read beside layer 0; port fixes: the next read starts at c0 + T (the port's first chunk is shorter), and the upload is marked by a polled sequence number instead of a host event wait, which deadlocked prompts past ~4K tokens under the Level Zero v2 adapter - Niko1221#363 group stride + fused SwiGLU/q8_1 for the PCIe expert call, re-applied to the port's lane kernels (fp contract off, as upstream's HIP form) - Niko1221#407 --adapt-tuned (opt-in), Niko1221#413 key-head DeltaNet recurrence (opt-in via STRATA_GDN_KEYHEAD=1: 8% slower on the B70; its NVIDIA gate and SM-holding parity bench not ported) Tested on the B70: native_grouped_parity, iq_multi, gr, qsa, kv_hybrid, quantize_act, qsa_prompt_attn parity pass; Coder 19/2,184-token, IQ2_XS and 40K outputs identical to 0.1.33; Coder 2,184-token prompt 784 -> 825 tok/s; 128K int8 KV streaming 895 / 67.0 tok/s; IQ2_XS decode +1.7% (Niko1221#363). Co-authored-by: sergqwer, constantindjonkam, architectds, BlueKingMuch (upstream PR authors) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rb4SRxFuLpffQAAXBf4HxA
|
Released in 0.1.38: the stager waits for a buffer's previous DMA on every job. Merged under your name (GitHub doesn't show it as merged because it went in by hand). Thank you! |
…0.1.35 One dpct run of upstream main + the seven PRs, 3-way merged into the files they touch (sycl/tools/merge_upstream.py); their header changes are forked into sycl/include until upstream merges them. - #385 stager waits for a buffer's previous DMA on every job (port: polled seq) - #463 decode waits for an adaptive swap before reading residency - #453 drafter's batched K/V on the KV-streaming ring - #374 first chunk's PLE rows read beside layer 0; port fixes: the next read starts at c0 + T (the port's first chunk is shorter), and the upload is marked by a polled sequence number instead of a host event wait, which deadlocked prompts past ~4K tokens under the Level Zero v2 adapter - #363 group stride + fused SwiGLU/q8_1 for the PCIe expert call, re-applied to the port's lane kernels (fp contract off, as upstream's HIP form) - #407 --adapt-tuned (opt-in), #413 key-head DeltaNet recurrence (opt-in via STRATA_GDN_KEYHEAD=1: 8% slower on the B70; its NVIDIA gate and SM-holding parity bench not ported) Tested on the B70: native_grouped_parity, iq_multi, gr, qsa, kv_hybrid, quantize_act, qsa_prompt_attn parity pass; Coder 19/2,184-token, IQ2_XS and 40K outputs identical to 0.1.33; Coder 2,184-token prompt 784 -> 825 tok/s; 128K int8 KV streaming 895 / 67.0 tok/s; IQ2_XS decode +1.7% (#363). Co-authored-by: sergqwer, constantindjonkam, architectds, BlueKingMuch (upstream PR authors)
…iko1221#374 Niko1221#363 Niko1221#407 Niko1221#413 onto 0.1.35 One dpct run of upstream main + the seven PRs, 3-way merged into the files they touch (sycl/tools/merge_upstream.py); their header changes are forked into sycl/include until upstream merges them. - Niko1221#385 stager waits for a buffer's previous DMA on every job (port: polled seq) - Niko1221#463 decode waits for an adaptive swap before reading residency - Niko1221#453 drafter's batched K/V on the KV-streaming ring - Niko1221#374 first chunk's PLE rows read beside layer 0; port fixes: the next read starts at c0 + T (the port's first chunk is shorter), and the upload is marked by a polled sequence number instead of a host event wait, which deadlocked prompts past ~4K tokens under the Level Zero v2 adapter - Niko1221#363 group stride + fused SwiGLU/q8_1 for the PCIe expert call, re-applied to the port's lane kernels (fp contract off, as upstream's HIP form) - Niko1221#407 --adapt-tuned (opt-in), Niko1221#413 key-head DeltaNet recurrence (opt-in via STRATA_GDN_KEYHEAD=1: 8% slower on the B70; its NVIDIA gate and SM-holding parity bench not ported) Tested on the B70: native_grouped_parity, iq_multi, gr, qsa, kv_hybrid, quantize_act, qsa_prompt_attn parity pass; Coder 19/2,184-token, IQ2_XS and 40K outputs identical to 0.1.33; Coder 2,184-token prompt 784 -> 825 tok/s; 128K int8 KV streaming 895 / 67.0 tok/s; IQ2_XS decode +1.7% (Niko1221#363). Co-authored-by: sergqwer, constantindjonkam, architectds, BlueKingMuch (upstream PR authors)
…iko1221#374 Niko1221#363 Niko1221#407 Niko1221#413 onto 0.1.35 One dpct run of upstream main + the seven PRs, 3-way merged into the files they touch (sycl/tools/merge_upstream.py); their header changes are forked into sycl/include until upstream merges them. - Niko1221#385 stager waits for a buffer's previous DMA on every job (port: polled seq) - Niko1221#463 decode waits for an adaptive swap before reading residency - Niko1221#453 drafter's batched K/V on the KV-streaming ring - Niko1221#374 first chunk's PLE rows read beside layer 0; port fixes: the next read starts at c0 + T (the port's first chunk is shorter), and the upload is marked by a polled sequence number instead of a host event wait, which deadlocked prompts past ~4K tokens under the Level Zero v2 adapter - Niko1221#363 group stride + fused SwiGLU/q8_1 for the PCIe expert call, re-applied to the port's lane kernels (fp contract off, as upstream's HIP form) - Niko1221#407 --adapt-tuned (opt-in), Niko1221#413 key-head DeltaNet recurrence (opt-in via STRATA_GDN_KEYHEAD=1: 8% slower on the B70; its NVIDIA gate and SM-holding parity bench not ported) Tested on the B70: native_grouped_parity, iq_multi, gr, qsa, kv_hybrid, quantize_act, qsa_prompt_attn parity pass; Coder 19/2,184-token, IQ2_XS and 40K outputs identical to 0.1.33; Coder 2,184-token prompt 784 -> 825 tok/s; 128K int8 KV streaming 895 / 67.0 tok/s; IQ2_XS decode +1.7% (Niko1221#363). Co-authored-by: sergqwer, constantindjonkam, architectds, BlueKingMuch (upstream PR authors) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rb4SRxFuLpffQAAXBf4HxA
Stager::workwaits for a buffer's DMA only from a generation'skRing-th job on (j >= kRing). A generation's firstkRingjobsmemcpyinto their pinned buffers straight away.So the previous generation's last DMAs from those buffers are only known to be done where something else waits for them:
stream_all_min): the routing sync (cudaStreamSynchronize(m.cs)) before the layer'sstart();stream_allchunks: the sync at the end of a chunk, which runs only with an MTP drafter (on_chunk) or a layer split (on_stage_chunk).That leaves a window in two cases:
stream_allchunk that ends without that sync (no--mtp);In that window, the next chunk's first jobs can overwrite a pinned buffer that a
cudaMemcpyAsyncon the copy stream is still reading. It only matters with unpinned blobs, which go through the stager: the RAM-budget tier, or a partially pinned arena.The fix: the event is now waited for on every job. An event that was never recorded, or has already completed, returns at once. For
j < kRing, no job of the current generation can have recorded the event, so the wait is exactly the previous generation's last DMA from that buffer.We found it in an audit of our fork. We have not seen it corrupt a run: it needs that timing and the unpinned path.
Measured:
--mmap-experts --resident-budget-gib 16: 12,144 of the 48,668 streamed experts went through the stager.🤖 Generated with Claude Code
https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio