feat(gguf,dsv4): GGUF block-dequant + DSv4 architecture kernel surface#243
Conversation
002b89d to
6e36b69
Compare
b245fdc to
9fcef42
Compare
df839db to
f6a1382
Compare
Status — review pass completeAudited this branch against the conventions in #200+ / CONTRIBUTING / docs and fixed the findings. 3 logical commits ( Changes from the review:
Green locally: One open design question for @ekryski above (gating the |
844f121 to
c31724e
Compare
| matches!( | ||
| self, | ||
| DType::I32 | DType::I8 | DType::I4 | DType::U8 | DType::U32 | DType::U64 | DType::I64 | ||
| DType::I32 |
There was a problem hiding this comment.
Should have a constant somewhere to avoid brittle match statement.
There was a problem hiding this comment.
Good call. Switched is_float/is_integer from a non-exhaustive matches! to an exhaustive match — now adding a DType variant fails to compile until it's classified in both, so they can't silently disagree or miss a new type (which is exactly how U16 could've slipped through). Went with the compiler-enforced match rather than a shared const since that catches the omission at build time instead of relying on the list staying in sync; happy to swap to a const set instead if you'd rather have one source of truth to reuse elsewhere. Pushed.
|
I might already have |
|
@ekryski — one design decision I'd like your call on before this merges:
This branch adds I left it unconditional because the generated binding surface is already consumed broadly on the FFAI side, so gating is a cross-repo change. Which do you prefer — gate it (I'll set the flag on the MMA/bm64 kernels and coordinate the FFAI binding regen), or keep it emitted for all? (FYI, unrelated: I pulled an opportunistic |
c31724e to
15f8731
Compare
Merge coordination — assuming #247 lands firstUpdating my earlier note: since Conflict surface is small — two files:
Structural note (unchanged): #243 adds Post-#247-rebase to-dos I'll do (depend on #247's
Cleanup since the last push: removed two dead negative-result kernels ( |
717d99e to
2f763cf
Compare
|
@ekryski re |
3737fd3 to
3d2bffb
Compare
|
@ekryski CI is fully green now ✅ (Test 39s — the 57 NAX/MPP cooperative-tensor tests correctly [SKIP] via your #258, no longer failing). Heads-up on a real bug I found and fixed while getting here — worth knowing about: Q2_K dequant test was silently validating the wrong layout
So the production kernel was always correct — the test scaffolding was wrong, which is the dangerous kind: a green-looking harness that doesn't exercise the real on-disk layout. Fix: a shared It hid from my local runs because my filter ( Also in this push: bumped And a correction to my earlier NAX comment on #247I was wrong that those were M5-hardware-gated. Your #256/#258 archaeology shows it's the macOS 26.4 runtime Metal compiler choking on Apple's own MPP |
The #[kernel] macro lowered Tensor<u16> args to float* in the signature parser, silently corrupting any u16 kernel. Map u16/ushort to DType::U16.
…passes - DType::U16 wired through core/codegen/macros for IQ2 raw-block view reads; is_float/is_integer use exhaustive matches so a new dtype can't silently misclassify. - dispatchThreadgroups Swift-wrapper emit variant for the bm64/coop_tile MoE GEMMs, with an emit unit test pinning the binding + dispatch shape. - BTreeMap->FxHashMap in the order-independent IR passes (perf).
IQ2_XXS & Q2_K MoE GEMMs (gemv-rows, bm64 amortized MMA, zero-copy view-bm64 reading raw resident blocks via u16), Q8_0 GEMMs + grouped O-LoRA gemv, partial-RoPE/SwiGLU/SDPA prefill+decode, GPU-side top-k routing. Every kernel ships a GPU correctness test vs a CPU reference in this commit.
3d2bffb to
88a6d7d
Compare
|
Merging! We'll do two follow up PRs once this and #252 merge.
|
## What this fixes Sibling of #264. While verifying that fix I swept the whole Q2_K correctness family and found a **second** test with the identical bug: `moe_bgemm_q2k_mpp_correctness` failed with **cosine 0.604 < 0.99**. Same root cause — the CPU oracle unpacked the 2-bit quants with the naive **4-consecutive-per-byte** mapping (`q_byte = in_block/4`, `shift = (in_block%4)*2`), while the kernel under test and the validated `gguf_dequant_q2_k` both use the canonical llama.cpp `dequantize_row_q2_K` layout (2 halves of 128 → 4 j-groups of 32 → two runs of 16 at a shared `jg*2` shift). Correct kernel, wrong oracle. ## The fix Test-only. Adds the same `q2_k_qpos(i) -> (qs_byte, shift)` helper #264 introduces; the oracle now reads the same `qs` byte + shift as the kernel (scale index is the canonical `i / 16`). **Kernel untouched.** ## Why CI didn't catch it `moe_bgemm_q2k_mpp` is a cooperative-tensor (MPP) kernel — its correctness test only builds/runs on Apple10+ / macOS 26.5 (skipped on the macOS-26.4 CI image per #258). It has only ever run on a local M5, so the naive oracle slipped through from #243. ## Verification `test bgemm_q2k_mpp_matches_gemv_oracle ... ok` (cosine ≥ 0.99). Ran the full Q2_K correctness set on M5 / 26.5: the only two failures were this and #264's `moe_gather_down_q2k`; the other five (`bm64`, `view`, `gemv_rows`, `gemv_ws`, `q2k_view_u16`) pass. So #264 + this close out the family. Pairs with #264 (cc @ekryski).
Summary
Companion to thewafflehaus/FFAI#17 — adds the GPU kernels FFAI's GGUF loader + DSv4 family forward path dispatch into. Started as the three GGUF block-dequant kernels; grew to cover the full DSv4-Flash architecture surface as the FFAI side caught up.
GGUF block-dequant kernels
All three generic over `T = f32 / f16 / bf16`. Host produces the GPU-resident split (packed quants + per-block scales + LUT tables), kernel does `out[i] = scale_block × codebook_decode_at(packed_bits)`. Output dtype follows `T` via implicit Store coercion.
DeepSeek-V4 architecture kernels
Plus utility: `ffai_vector_add` (generic elementwise out[i] = a[i] + b[i]) — `Ops.add` already existed but routed through a different binary kernel; this one is used by Ops.add's f32/f16/bf16 paths for the per-expert MoE accumulator.
Validation
All 14 kernels have CPU oracle + GPU correctness tests in `kernel_tests_harness`. Tolerances within the standard f32 / f16 / bf16 bands (elementwise 1e-4 / 5e-3 / 5e-2; SDPA 1e-3 / 3e-3 / 1.5e-2). Validated end-to-end via the FFAI integration tests against the real 86 GB DSv4-Flash GGUF on M5 Max.
DSL gotchas surfaced + documented
Three codegen pitfalls hit while writing the DSv4 kernels (notes in `feedback_metaltile_dsl_codegen_pitfalls.md` in the project memory):
IR codegen tests (`every_registered_benchspec_codegens`) pass for all three pitfalls, but real-GPU dispatch via `kernel_tests_harness` fails with `MSL library compilation failed: use of undeclared identifier vXX`. Fix patterns documented for future kernel work.
Target
Cross-fork PR: `TheTom/metaltile:tom/wip/gguf-dequant` → `0xClandestine/metaltile:dev`. Branch is on a personal fork because cross-repo CI pins in the FFAI side need to point at a stable target (org branch).