Raise qmv batch limit for large matrices on M5-class GPUs#3791
Raise qmv batch limit for large matrices on M5-class GPUs#3791pierre427 wants to merge 1 commit into
Conversation
On g17 hardware the qmv_wide kernels stay ahead of the qmm path well past
the generic non-'d' fallback limit of 10. Measured on M5 Max (g17s) with
affine 4-bit/8-bit weights (group_size 64) at D=8192,
O in {1024, 8192, 28672, 250112}: qmv_wide is ~18% faster at M=12
(241.5ms vs 294.6ms whole-model forward on a 70B) and still ahead at M=16.
Raises the large-matrix limit to 16 for gen>=17 non-'d' GPUs; small and
mid shapes keep the existing fallback values. Mitigates the small-M
speculative-decoding verification cost discussed in ml-explore#3553.
|
Friendly bump — this is a small, low-risk change (gen-17 large-matrix |
|
Ran the small/mid bucket sweep I offered above, on the same M5 Max (g17s). TL;DR: I don't think small (18) or mid (12) should move — the large-bucket change here is the only one with a measurable effect. Method: I added a bench-only runtime override to 1. Isolated per-op microbench (4-bit affine, group_size 64; min of 60 reps, 2 trials): small (1024², 2048²) and mid (4096², 2880×4096, 4096×2880) shapes read vector ≈ qmm within ~1–2% across M=1–24 (median vec/qmm 0.99–1.03). But as a sanity check I included the large 8192×8192 shape as a positive control, and the microbench fails it — it reads M=12 as a tie (vec/qmm ≈ 1.00), not the ~18% win this PR measured whole-model. So an isolated single-matmul benchmark is too insensitive to resolve this; the large-bucket win looks like a whole-model/system effect (split-K launch cost amortized across the layer chain with a warm cache), not an isolated-kernel property. 2. Whole-model A/B (matching this PR's own methodology) on
Median force-vec/force-qmm over M≥12 = 0.997 — within noise across the whole speculative-verify window; the shipped default tracks both. So for a real small/mid-dominated model the limit choice doesn't materially affect decode/verify throughput. Net: keeping small at 18 and mid at 12 (the inherited fallback values) looks right for gen-17 — no data to justify changing them, which is consistent with this PR only touching the large bucket. Happy to share the harness or run other shapes if useful. |
|
@pierre427 this looks great. I will try to get some numbers from more architectures to in-a-way redo this heuristic and then merge. |
Proposed changes
get_qmv_batch_limitcurrently sends gen-17 (M5-class) GPUs down the genericnon-
'd'fallback, which caps the qmv/qmv_wide path at M<10 for largematrices. Measured on an M5 Max (
applegpu_g17s), theqmv_widekernels stayahead of the
qmmpath well past that limit on large shapes. This PR raisesthe large-matrix limit to 16 for
arch_gen >= 17non-'d'devices; small andmid shapes keep the existing fallback values (no data to justify changing
them).
This mitigates the small-M quantized-matmul cost step discussed in #3553 for
the M=11–16 band, which matters for speculative decoding: verification of
multi-candidate / tree / long prompt-lookup proposals lands exactly in that
window. #2031 notes these limits are empirical and machine-dependent; gen-17
hardware postdates the tunings there.
Measurements
Apple M5 Max, 128GB (
applegpu_g17s), macOS 26. Whole-model forward cost vsrow count M against a warm 400-token KV cache, min of 6 reps. Model: 70B dense
llama-arch (LLM360 K2-V2), affine 4-bit, group_size 64 (D=8192; O spans 1024 /
8192 / 28672 / 250112 across layers).
Same model at affine 8-bit: M=12 326.7 → 304.1 (−7%).
For reference, the 0.31.2 release (no qmv_wide kernels) costs 298.5 ms at
M=12 on the same 4-bit model, and end-to-end speculative decoding on this
hardware improves from ~18 tok/s (release) to 24.5 tok/s (main + k=3 chain
with a 0.6B draft), with the M=11–16 window enabling wider verification
schemes this change dispatches to the faster path.
Repro
Happy to run additional shapes/configs on this hardware if useful for tuning
the small/mid buckets too.