Repository navigation
Conversation
|
Hello @Mirrdhyn, Thank you for the Qwen3.8-27B backend on Intel Arc Pro B70 (Xe2) over Level Zero. It serves Two things have to change before this is ready.
Lines past 120 columns, the longest in We cannot run this here. On an Intel Arc Pro B70, with Level Zero,
The prompt path includes the chunked GDN kernel ( Thank you again. |
…ory, refused when they do not fit
|
Thanks for the review. Both changes are in 25ef56c:
Receipts on an Arc Pro B70 (power-capped at 230 W), Level Zero, ocloc for bmg, nGEN headers,
Speed against llama.cpp on the same card (build 8c2134a,
IPEX-LLM is archived, so I did not run it. |
|
Comparison as you set it (Qwen3.8-27B, Arc Pro B70 power-capped at 230 W, PR head 25ef56c). llama.cpp 8c2134a:
The three decode runs give the same rate to 0.1 tok/s. Q4_K_M is not measured on the 27B. The FP64 reference for the int4 GEMM follows in a separate comment. |
|
Hello @Mirrdhyn, Thank you for the Qwen3.8-27B server on the Arc Pro B70, and for taking the captured SPIR-V out of the tree and sizing streams from the device's free memory. This is accepted. It lands on your B70 receipts plus our host checks: build, host tests, lean, privacy, and the copy scan. We wrap native/xpu.zig:179, docs/xpu/README.md:43, and docs/xpu/NAVIGATION.md:111 at landing. KV stays bf16 unless the int8 cache is asked for. Your FP64 reference for the int4 prompt GEMM, per projection class, is welcome. That reduction order differs from Metal and CUDA. Thank you again. |
…rrors, teacher-forced fidelity (XPU_FIDELITY)
|
One change since 25ef56c, in 913cf15: the int4 group means are stored ×256 so the low half of their fp16 hi+lo pair stays normal (it fell into subnormals on layers 0–1 of FP64 reference (
The head runs on decode only, so its worst column is over 8 rows, against 24 for the other references. Teacher-forced fidelity ( Receipts on 913cf15 (Arc Pro B70 power-capped at 230 W,
MLX 4/64, W4A8 ( |
…mpt kernels at any length; a short rest joins the last chunk
… xpu-tests), skipped without a device or a model
|
Three commits since 913cf15. d1906c3, prompt seams. The rule you set on #523 also applied here: the server cut prompts at message boundaries, and a chunk of 16 rows or fewer ran the decode kernels (serial GDN, decode attention and norms; the int4 GEMMs were already bit-equal between the two paths, checked on real weights). The same ids sent as a chat or through 402d09a, dad16a9, tests. Stream admission is a pure function with host tests in |
…ths on the same rows (XPU_FP64_REF); the fidelity reference says what it replaces
…s, as precise as the serial decode recurrence
|
Two commits since dad16a9. Fidelity reference (618b196). To be precise about what the earlier fidelity counts measure: the GDN prompt path (489baa2). Measuring the state recurrence itself against FP64 ( The cost is prompt speed: cold 1,929 / 1,855 / 1,632 / 1,404 tok/s at 2k / 8k / 32k / 64k, 5–6 % below the previous head; decode is unchanged (33.6 tok/s, DFlash2 123.2 code / 99.1 chat). All receipts were rerun on 489baa2: drafted equals |
… terms after a power-of-two row scale
|
GDN prompt path, cheaper form (17facba). The three bf16 terms of 489baa2 cost the 35B MoE 14–21 % of its prompt, where the GDN weighs more. Each pair of fp32 operands now enters fp16 DPAS as hi + lo terms after a power-of-two row scale (the row's largest magnitude in [2^14, 2^15), its exponent kept per row and undone on the fp32 result): three products instead of six for S·Wᵀ and P·U, two instead of three for Q·Sᵀ, with W, HS and VN stored as two fp16 planes; the products against bf16 k and v keep three bf16 terms. Measured against FP64 on y before its bf16 rounding (the fp32 output of the chunked kernel and of the serial decode on the same rows; layers 0, 1, 30 and 62; 512 and 4,096 rows; GPTQ and MLX), the prompt path is at or below decode in every layer (1.0–4.6e-7 against 1.2–6.3e-7), with one cell above decode but below an fp32 sequential sum (3.2e-7 against 2.8e-7 decode and 3.4e-7 sequential). The final state is 2.2e-7–1.0e-6 against 3.8e-7–2.2e-6 for decode, and 100 % of the bf16 outputs are within 1 ulp. Cold prompt is 1,937 / 1,878 / 1,643 / 1,416 tok/s at 2k / 8k / 32k / 64k (489baa2: 1,929 / 1,855 / 1,632 / 1,404; dad16a9, before the GDN fix: 2,048 / 1,979 / 1,718 at 2k–32k); decode is unchanged (33.6 tok/s, DFlash2 123.0 code / 102.3 chat). All receipts were rerun on 17facba: drafted equals |
|
Thank you, @Mirrdhyn, for separating GEMM and recurrence fidelity and reporting the prompt-speed cost of the new precision path. At 489baa2, the earlier safety gaps remain. Please send a follow-up closing these allocation, input-validation and cleanup paths before we move this into landing checks. Posted by Ash's AI Assistant Synthena |
What this changes
A native Intel XPU backend (Arc Pro B70, Xe2, Level Zero) serving Qwen3.8-27B through the lane host, new files only and no core changes. Proposal and questions: #801.
Receipt
c36b536d) + this commit; no MLX or PyTorch at run time; Intel Arc Pro B70 32 GB (power-capped at 230 W), Ubuntu 26.04.1, kernel 7.0.0-38, compute runtime 26.35.39758.10, Level Zero loader 1.32.0, xgrammar v0.2.8, Zig 0.17.0;SergiioB/Qwen3.8-27B-GPTQ-Int4-sym-G128-MTP-BF16at9d189a60, drafterz-lab/Qwen3.8-27B-DFlash2.tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false:--levels 1,2,4,8, temperatures 0 and 1, four configurations and--parallel 1: 80/80 series equal alone and serial; runner contracts (drafted == plain for chains and trees, 8 slots in shared rounds == solo) 30/30; identicaltoken_shaand output hashes before and after the rebase at 2k to 64k.tools/bench_openai.py: no previous release has this backend; the same port on 1.0.7 → this commit:fibonacci-raw142.1 → 142.2 tok/s,gpu-chat-no-think90.3 → 90.3 tok/s. vLLM 0.31.0 XPU on the same card: 78.6 tok/s for one request.tools/prefill_cold.py: that script is not in the repository, sotools/bench_cache.py --require-coldwith exact token arrays and--prompt-cache-gib 0: 2k / 8k / 32k / 64k 1,907 / 1,916 / 1,687 / 1,453 → 2,049 / 1,963 / 1,713 / 1,470 tok/s (vLLM 0.31.0: 1,785 at 1k, 1,730 at 8k).zig build test700 passed, 0 failed, 5 skipped (46/46 steps);tools/zig/lean_check.py538, the 1.0.9 baseline;zig fmt --checkclean.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.zig build testruns the stream admission rule (xpu_admit.zig) on the host.zig build xpu-testsbuildstf-xpu-qwen27-means-test(group means against FP64; fails before 913cf15, passes after) andtf-xpu-qwen27-seam-test MODEL(a prompt cut at 64, 1024 or whole gives the same logits; fails before d1906c3). Both printskipped:and exit 0 without a Level Zero device or a model.)Summary
A native
xpubackend for the Zig engine. It drives an Intel Xe2 GPU (Arc Pro B70, 32 GB) directly through LevelZero, with no PyTorch, SYCL or Python at run time, and serves Qwen3.8-27B (
qwen3_5) throughtensorfold-native servewith the DFlash2 drafter. Two checkpoint formats: symmetric GPTQ 4/128 and MLX affine 4/64.
zig build xpu-native xpu-qwen27 -Dngen-include=<oneDNN nGEN headers>. Nothing changesfor Metal, CUDA or HIP builds.
Lone.resumes,hooks.resumed) as theyare in 1.0.9;
build.ziggains two lines. Every--parallelvalue, 1 included, goes through the lane host.oclocfor the device, plus the int4 prompt GEMMs generated in ISA by nGEN atbuild time (
zig/tools/xpu/w4_ngen.cpp); everything is embedded in the binary.stream, prompt cache (
--prompt-cache-gib), structured output (xgrammar masks, argmax on the device).XPU_PREFILL_INT8=1, int8 activations on int8 DPAS) and, onHadamard-rotated weights (
zig/tools/xpu/rotate_w4.py), W4A4 (XPU_PREFILL_INT4=1).Docs:
docs/xpu/README.md(options, numbers, what is verified),docs/xpu/NAVIGATION.md(code map, request path,contracts) and
docs/xpu/RECIPE-qwen38-27b-b70.md(how the served setup is built).Contracts
Verified at the same checkpoint, backend, runtime and settings, for the four configurations below (GPTQ, GPTQ + W4A8,
MLX, rotated + W4A4) and for
--parallel 1:"draft": falseoutput, token for token: chains and trees, perfect and wrong drafts, greedyand sampled (
XPU_VERIFY_TEST, andbench_concurrent.py --serialend to end).(
XPU_MULTI_TEST, andbench_concurrent.py --aloneat 1, 2, 4 and 8 streams, temperatures 0 and 1).zig build test46/46 steps, 700/705 tests passed, 5 skipped (the suite's own skips).python3 tools/zig/lean_check.py: 538 problems, the same count as the 1.0.9 baseline (0 added); every XPU file isat most 600 lines.
The int4 GEMM's reduction order differs from Metal and CUDA (DPAS partial sums per group, then the scale, then the
bias by DPAS); the decode, verify and prompt kernels share one order, which is what makes drafted == plain hold. I have
not built a per-projection FP64 reference yet: tell me which form you want and I will attach it.
Receipts
Machine: Intel Arc Pro B70 (32 GB, power-capped at 230 W), Ubuntu 26.04.1 LTS, kernel 7.0.0-38, Intel
compute runtime 26.35.39758.10 (
libze-intel-gpu1,intel-opencl-icd,intel-ocloc), Level Zero loader 1.32.0,xgrammar v0.2.8, Zig 0.17.0, Python 3.14 for the clients. Checkpoint:
SergiioB/Qwen3.8-27B-GPTQ-Int4-sym-G128-MTP-BF16at9d189a60e4c0ad7f9f47cd94bfa393ca10b3924e(Apache-2.0), servedwith its own tokenizer; drafter:
z-lab/Qwen3.8-27B-DFlash2(a mirror ofincoai/Qwen3.8-27B-DFlash2), the repository the other backends use. One model process on the machine.Cold prefill, one stream,
--prompt-cache-gib 0, fresh state, 16 output tokens, exact token arrays (the first2,048 / 8,192 / 32,768 / 65,536 tokens of LICENSE, CONTRIBUTING.md and
zig/src/coreconcatenated, encoded with thecheckpoint's tokenizer),
cached_tokens0 on every request. tok/s = prompt tokens / time to first token.The same port on 1.0.7 (before this rebase): 1,907 / 1,916 / 1,687 / 1,453, identical output hashes.
Served decode (
bench_openai.py --tokens 256 --reps 3 --temperatures 0,--parallel 8, GPTQ default): 142.2tok/s on
fibonacci-raw, 90.3 tok/s ongpu-chat-no-think.Concurrency (
bench_concurrent.py --tokens 256 --reps 3 --temperatures 0 --levels 1,4 --alone --serial):Against vLLM 0.31.0 XPU on the same card and checkpoint (official image, MTP 4, fp8 KV, prefix cache off), same
clients:
No previous TensorFold release has an XPU backend, so the before/after comparison above is this port on 1.0.7 versus
1.0.9. Not run: 128k and the native window (the B70 holds a 69,632-token context with one stream at the default
prompt-cache budget); Metal, CUDA and HIP (no change to their code paths).
Notes
zig/src/xpu,zig/src/native/xpu*.zig,zig/kernels/xpu,zig/tools/xpu,zig/build/xpu.zig,tools/xpuanddocs/xpu.zig/kernels/xpu/qwen27/triton/prompt_attention.spvis the Triton prompt-attention kernel of the Python port, kept asSPIR-V behind
XPU_ATTN_TRITON=1for comparison; the default is the backend's own DPAS kernel.