Repository navigation
Conversation
…to back so they share it in L2 The attn_decode grid becomes (rows, heads, slices); each work-group's arithmetic is unchanged, so outputs are bit-identical (refs ashhart#2543).
|
@SergiioB, the grid-only change preserves each row's arithmetic, slice order, subgroup reduction and BF16 store. The replacement contract and the matching main/drafted/plain hashes on the B70 support that argument. This keeps the wider-slice proposal separate, as agreed in #2543. The agreed device gate is still open: Please also make the performance receipt reproducible: retain the public prompt inputs, comparison command or script, raw per-request results, full build/checkpoint/drafter revisions and binary hashes, including the compiler workaround used on both sides. The current summaries omit token digests for eight timed main requests. An optimization-ledger note should identify this as the grid-only change and retain the stated unrun cases. Multi-stream and int8-cache qualification remain deferred as agreed, rather than passed. |
|
Independent run of this PR on a second Arc Pro B70 (PCIe 5.0 x16), including the three paths your receipt lists as not run, in case it helps the review. Setup. Your 6 commits cherry-picked onto main Exactness. Every cell below gives the same reply sha256 on main and on the branch, and drafted equals
Decode tok/s, drafted, main → branch (code / prose):
Reading the diff. Only the Not run here: sampled decoding, |
|
@SergiioB, thanks. The diff is a pure grid remap, and each work group still writes the same partials, so we accept the bit-exactness argument. Thanks also to @Mirrdhyn for the independent B70 run: matching hashes on GPTQ, MLX and Before landing, please:
|
|
Numbers for item 6, and a data point for item 1, from the same B70 (PCIe 5.0 x16). Stack since my first run: kernel 7.0.0-43, compute-runtime 26.35.39758.21, IGC 2.41; same binaries (main Item 6: with
Per-kernel GPU time (dev runner
So at short context with 256-byte int8 rows the new order costs more than it saves in Item 1, What I'm looking at next, in case it helps you or overlaps with your own plan: the bits are identical and the diff only remaps group ids, so this points at memory locality rather than at the kernel's code. Two hints: |
|
Thanks @SergiioB, and thanks again @Mirrdhyn for the follow-up: the depth sweep and the per-kernel times make the Nothing has changed on the branch since our last comment, so the list from then still stands:
We can't run XPU ourselves, so your B70 numbers and @Mirrdhyn's are the device evidence. Once these are in, we'll approve the CI workflows on your new head. When CI is green, it can land after the current release. |
…ld (slices, heads, rows) grid It launches that grid only where it stays inside the buffers (no more slices than rows), so gate 3 goes red at 16 rows over 33 keys and the registration guards the launch order forward.zig uses. Co-authored-by: SergiioB <119968745+SergiioB@users.noreply.github.com>
…and its unrun cases Co-authored-by: SergiioB <119968745+SergiioB@users.noreply.github.com>
|
Thanks @SergiioB, and thanks again @Mirrdhyn for the B70 runs. We've done the items on our list that don't need an Intel card, as two commits on top of yours on this branch:
We have no Intel GPU, so we can't run the control. We built the contract runner against stand-in images to check that it compiles. Please run These still need your card:
Once these are in, we'll approve CI on the new head.
|
|
The follow-up I promised on 9 Nov on the ISA. Memory (VTune
The int8 path itself. Per key both paths issue the same 32 loads (16 for K, 16 for V), each one subgroup message of 16 bytes in int8 or 32 bytes in bf16, plus the two scale loads on the int8 path. In the disassembly the int8 convert is 4 operations per element against 1 for the bf16 expand, +14 % instructions per key compared with bf16. That comparison is int8 against bf16 on one binary; it does not explain the +14 % time between main and branch, where the code is the same. Two attempts not worth repeating.
The rule from item 6, old order for an int8 cache with few slices, still fits my numbers. My sweep's crossover is between 7,588 (−4.1 %) and 15,022 (+2.5 %) tokens, about 12.2K by interpolation, or about 380 slices on the 32-key split. That is a starting point, not a measured threshold, and as you wrote, switching would need the contract to cover both orders with measurements on each side. I'll run |
|
The new control goes red where you expected, at 16 rows over 33 keys: Summary: |
What this changes
attn_decodeon the Qwen3.8-27B XPU path now runs on a(rows, heads, slices)grid instead of(slices, heads, rows), so the tree rows of one key slice run back to back and share its K/V in L2. Per-work-group arithmetic is unchanged: outputs and tokens are bit-identical to main. The pairattn_decode+attn_mergeis registered in the XPU kernel contract as a replacement that must equal today's kernels byte for byte.1a5644892; merges cleanly ontofcf85f7).atc overlap --json:complete: false(limitationsotherPullRequestsLimit,pullFilesUnavailable,timeLimit), no overlaps reported. Manual check of the 200 most recent open pull requests: only shared build/doc files overlap (zig/build/xpu.zig,zig/build/kernel_contract.zig,docs/kernel-contract.mdin lfm2: DSpark drafting with owned context and confidence scheduling #1394, EXL3 Flash Next: host-resident K/V on the tier (6/8) #1522, xpu: LFM3-VL-2B on the Intel GPU (Iris Xe, no DPAS): pictures in, text out #1838, Metal: the 27B verifies 32 rows a pass on pre-M5 Macs #1841, MoE route tap: optional TF_ROUTE_TAP trace of global top-k #1886, RoPE: Qwen3.8-27B on XPU from core's exact helper (#1852 batch 8; 1-ulp value changes) #2000, Living Weights on Qwen4 dense, step 2: the native CUDA and Metal learner (experimental, --slide refused) #2054, Living Weights on Gemma 4, step 2: the native GeGLU learner on CUDA and Metal (experimental, --slide refused) #2062, kimi: experimental K3.1 index operators on Metal, native serving stays capped #2228, qwen3-asr: the XPU binding on Gen12LP (#2105, stacked on #2239) #2255). Each of those already conflicts with current main on its own; none touchesdecode.cl,forward.zigor the contract sources added here.Checks on this head
a1d896a88(6 commits: grid order, contract registration, NAVIGATION line, widths 2/4/8/12, contract doc, receipts).1a5644892(5,936 files) and 116 on this head (5,939 files); 0 new findings.tf-xpu-contract-run --device 0(BMG-G31), rerun on this head's contract sources with the exit status recorded:SUMMARY bmg-g31 0xe223 10 kernels: 10 pass gates 1-4, 0 fail, 0 known findings; 6 controls: 6 red as planted, 0 missed; 0 limit problems, exit 0. Attention: 20 shapes bit-equal to the kernel it replaces.xpu-kernel-contract-limits: every registered launch fits bmg-g31, every record current, every control red.zig build test --summary allon Linux x86_64 at this head: 607/607 steps succeeded, 7,925 of 7,991 tests passed, 66 skipped, 0 failed (exit 0). Attention registration tests 19/19;test-kernel-contract222 executed + 13 cached, 0 failed.test-goldenand fuzz suites were not run locally.zig build --summary all(plain build) at this head: 33/33 steps succeeded, exit 0.xpu-qwen27-testson one B70, main and this branch: seam pass (0/248,320 differing logits at cuts 64 and 1,024) and close pass on both. means fails on both, identically: it printsgroup means: worst error / Σ|terms|: prompt 5.12e-5, decode 1.86e-5 (bound 2e-6)and then exits 139 (segfault), on unmodified main and on this branch. The group-means/GEMM path is unchanged here; this PR does not fix it. The "all device tests pass" part of the gate is open pending your call on this pre-existing failure.XPU_KV_INT8=1;--parallelabove 1 (multi-stream rounds); resumed prompts from the prompt cache (--prompt-cache-gib 0throughout); sampled decoding; any GPU other than BMG-G31; QPARTS != 1 builds.Receipt
--parallel 1 --context 139264 --prompt-cache-gib 0, one discarded warmup, drafted and"draft": false.attn_prompt, unchanged.1a5644892, both built with Zig 0.17.0 and ocloc 26.05.37020 plus one local build change that drops-cl-intel-128-GRF-per-threadfrom the Gemma 4 prompt-rows kernels (ocloc 26.05 rejects it; not part of this PR). Ubuntu 26.04, kernel 7.0, xe driver, oneAPI 2026.1. Intel Arc Pro B70 (BMG-G31, 32 GB), 230 W cap. CheckpointTensorFold/Qwen3.8-27B-MLX-4bit@22d8d538, drafterz-lab/Qwen3.8-27B-DFlash2, bf16 KV. The whole-model branch binary was built at the tree of42473ce29(grid order and NAVIGATION line); later commits change only contract sources, docs and receipts, with production decode/forward unchanged.token_shafrom the server log of each request):"draft": false"draft": false596a68a0fce5×2a6b86fdf8992×23cb4af2530db×246ebf41df2f3×2150f6d329941×24bf356e770cb×28d68ee4e9421×14fd3ed8293b5×1All four columns carry the same
token_shain every row (×n = requests). The retained server logs cover 46 of the 54 timed depth requests: main drafted hastoken_shafor n=2 below 130K tokens and n=1 at 130K tokens, while its speed medians use n=3 and n=2; those 8 earlier main requests have output-text hashes only, which also match. Short prompts throughtools/bench_openai.py:9ccc5ea1a3d7(fibonacci-raw) and703e2fba4510(gpu-chat-no-think) on both, 12 requests each side."draft": false(n=1 each): 32.0 / 30.4 / 23.4 / 12.8 (main) and 32.0 / 30.4 / 23.7 / 13.0 (branch). At 130,856 tokens main's drafted decode (11.4) is slower than its own"draft": false(12.8); on this branch drafted (15.1) is faster than"draft": false(13.0) again.tools/bench_openai.py --tokens 256 --reps 3 --temperatures 0, two alternated rounds: fibonacci-raw 131.9 / 131.9 (main) and 131.8 / 131.8 (branch); gpu-chat-no-think 87.8 / 87.8 and 87.7 / 87.8.attn_prompt, which this change does not touch; cold TTFT at 130,856 tokens is 133.9 s on both.Kernel contract
attn_decodefollowed byattn_mergeas one operator (bf16 Q rows, bf16 K/V cache, tree table → bf16 attention rows), replacing the1a5644892pair, whose source is kept inzig/kernels/xpu/contract_attn_upstream.cland run on the same inputs. Gate 3 is byte equality at 20 shapes: tree widths 1, 2, 4, 8, 12, 16 (heap-order parents) and visible keys 33, 34, 8,193, 32,768, 32,769, 32,770. Equality is shown for the combined operator's bf16 output, not for the fp32 partials separately; chains and other tree topologies are not fixtures.SUMMARY bmg-g31 0xe223 10 kernels: 10 pass gates 1-4, 0 fail, 0 known findings; 6 controls: 6 red as planted, 0 missed; 0 limit problems, exit 0.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. Drafted equals"draft": falseat every cell above; resumed-prompt and concurrent equality were not run.--drafter, no slower than without it, greedy and sampled. One stream greedy only; the widest admitted and sampled runs were not done.Revert:
git revertthe six commits; no format, switch or public interface changes.