Skip to content

Fuse dispatch for the legacy interleaved CQ4 GEMV#712

Closed
ncylich wants to merge 1 commit into
sme2-integrationfrom
il-fused-gemv
Closed

Fuse dispatch for the legacy interleaved CQ4 GEMV#712
ncylich wants to merge 1 commit into
sme2-integrationfrom
il-fused-gemv

Conversation

@ncylich

@ncylich ncylich commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Third mode of the panel-format campaign (stacked on #710, which stacks on #709): the panel GEMV driver's dispatch retrofitted onto the unchanged legacy interleaved micro-kernel, so legacy-format bundles get the modern scheduling with zero file-format change.

What changes

cactus_quant_4bit_gemv_interleaved previously paid three passes per call: a pool-parallel Hadamard transform with a condition-variable join, a serial per-group int8 quantize on the main thread, then a second static-partition dispatch with another cv join. It now runs the panel driver's structure in one dispatch:

  • phase A (per-group Hadamard + int8 quantize) stolen by workers behind a spin barrier
  • phase B dynamically steals 16-block chunks (64 channels, same economics as panel super-blocks)
  • main thread participates as worker 0 and spin-joins (no cv sleep)
  • same thread budget, via a shared cactus_quant_gemv_sb_per_thread() (CACTUS_GEMV_SB_PER_THREAD)

The 7-op inner loop, activation quantization math, and numerics are unchanged. CQ4 INTERLEAVED_4ROW only (the production legacy format); 1–3-bit wrappers untouched.

Tests

Existing IL oracle test (matmul_cq4_il[file], N=192) only exercises the serial path; added matmul_cq4_il_mt[file] (N=4164 → 1041 blocks → 66 chunks incl. a 1-block tail) to engage the multi-thread fused worker, phase-A stealing, and 4-chunk grabs. 36/36 matmul tests pass.

Results

M4 kernel level (Gemma shapes, alternating best-of-5):

shape IL old driver IL fused driver panel NEON
kv_proj 1×1536×512 44.7 GF 158.2 GF 125.3 GF
o_proj 1×2048×1536 59.2 188.4 170.7
down 1×6144×1536 153.8 268.1 229.3
lm_head 1×1536×262144 727.4 901.7 897.7

M4 E2E, legacy bundles (~1k-token prompt + 32 decode, alternating cycles, coherent output):

model prefill tok/s decode tok/s
gemma-4-e2b-it 264 → 302 (+14%) 41.4 → 49.2 (+19%)
qwen3-1.7b 279 → 279 36.8 → 52.3 (+42%)
lfm2-350m 142 → 183 (+29%) 137 → 173 (+26%)

On-device, legacy bundles (#698 harness, 512+32 spec, 3 alternating rounds, devices powered, Thermal Status 0):

device model prefill decode
Samsung SM-S942U1 gemma-4-e2b-it 312 → 304 (par) 24.7 → 26.2 (+6%)
qwen3-1.7b 98 → 99 (par) 19.5 → 23.1 (+18%)
lfm2-350m 70 → 105 (+51%) 66.4 → 101.7 (+53%)
Pixel 10a (Tensor G4) gemma-4-e2b-it 86 → 84 (par) 10.5 → 10.5 (par)
qwen3-1.7b 34 → 34 (par) 11.2 → 10.9 (par)
lfm2-350m 38 → 44 (+16%) 36.3 → 40.8 (+12%)

Dispatch overhead is a fixed per-call cost, so the win scales with call rate: largest for small models on fast cores, parity (no regression) where slow cores already sit at the DRAM roofline. Decode-side this mode matches or beats the panel path on every phone case measured (the IL inner loop is 7 ops/32 weights vs the panel's 9, which matters on Cortex-X4-class issue width); the panel format keeps its structural wins — M>1 GEMM without the per-call expansion tax, SME2 zero-copy, no runtime cache.

With this, the engine has three coherent modes: fused-IL NEON on legacy bundles (best phone decode), panel NEON (portable prefill/TTFT), panel + SME2 (M-class frontier).

Replace the legacy IL GEMV's three-pass dispatch (pool-parallel Hadamard +
cv wait, serial int8 quantize, static parallel_ranges + cv wait) with the
panel driver's single fused dispatch: group-stolen phase A behind a spin
barrier, dynamic 16-block-chunk stealing in phase B, main thread as worker
0 with a spin-join, shared CACTUS_GEMV_SB_PER_THREAD budget. The IL
micro-kernel is unchanged.

M4 kernel: kv_proj 44.7 -> 158.2 GF, o_proj 59.2 -> 188.4 GF. E2E decode
on legacy bundles: gemma-4-e2b-it +19%, qwen3-1.7b +42%, lfm2-350m +26%,
reaching panel-NEON parity on the unchanged file format.

Signed-off-by: Noah Cylich <noahcylich@gmail.com>
@ncylich

ncylich commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

Consolidating the stack into a single PR per review preference — this work now lives in #709.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant