Repository navigation
Conversation
|
Hi @discobot, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
updated to match the template, rebased on top of fresh main |
|
this enables more efficient speculative decoding on metal |
|
@ggerganov friendly ping |
|
Thanks a lot for tackling this :) the small-batch waste in the 5–16 range is a real pain point and a thin tile is a clean way at it. My main hesitation is maintainability, each new tile ends up being a near-copy of mul_mm gated by another hardcoded predicate like ne1<=16, and those predicates don't really generalize — e.g. I tried the same thin tile on f16 + long K and it was slower than 64×32 at small n, so the q4_0-tuned cutoff wouldn't carry over. So I've been poking at a PoC that makes the tile a template parameter picked from a small shape-indexed table, instead of a new kernel per shape — the optimal tile turns out to be continuously tunable. It's basically the same approach as #25750 , just applied to mul_mm. |
|
Love your approach, and agree that maintaining this zoo would be hard. |
|
@forforever73 End to end, gemma-4-26B-A4B q4_0: pp8 44.7 ms this PR vs 56.7 tile-poc. so you win on f16, I win on q4_0 small bs, the poc tunes the tiles but keeps the old mv_ext -> mm. so best possible solution seems to be your table + per-dtype switch point + thin q4_0 rows |
|
In the parameterized version, those three naturally fold into one. The thin q4_0 tile is simply one row in the table, and the switch point (ne11_mm_min) is another per-dtype parameter (like use_nr8), so both become part of the same shape-indexed lookup rather than separate knobs. PoC only tuned the tile while leaving the switch unchanged, which is why q4_0 at bs 5–8 never reaches the tuned tiles. I've already started working on this and hope to have a draft PR up in a few days. Happy to iterate on it together if you're interested. |
|
thank you, let me know if I can be of any help |
|
I'm just noticing this PR. Will take a look. |
The mat-mv kernels are compute-bound and scale ~linearly with the batch size, while the 64x32 mul_mm tile zero-pads 75% of the batch dimension at bs = 8. Route q4_0 x f32 to a 64x8 tile for bs 5..16: 2x at bs = 8 on M4 Pro (test-backend-ops perf 4096x14336), pp8 -19% end to end on gemma-4-26B-A4B q4_0. bs = 1 decode unaffected. Ref: ggml-org#25250 Assisted-by: Claude Fable 5
|
@forforever73 @masterFoad Should we revive work on this approach? |
|
@ggerganov Yes, happy to help revive this. The reported small-batch Q4_0 gains looks legit. I agree with @forforever73 's approach 100%: make the tile a template parameter to reduce duplication, and select the tile and switch point together from a table. I can help test on M5. The new @forforever73 do you have an updated branch we could build on? |
|
@masterFoad Thanks! I already have some work in progress on this. I’m currently on vacation, but I’ll push up a draft PR the day after tomorrow so we have a concrete branch to build on and benchmark against. |
|
I ran the M5 comparison I mentioned above. The new thin kernel is disabled on M5, but this PR still routes Q4_0 batches 5-8 from Tested on a base M5 (10-core GPU), comparing master test-backend-ops perf -o MUL_MAT -b MTL0 -p 'type_a=q4_0,type_b=f32,m=4096,n=[0-9]+,k=14336'Q4_0 x F32, M=4096, K=14336:
Four rounds in ABBA order, warm-up discarded. Latencies are medians of run averages; ratios are medians of paired PR/master ratios. The regression appeared in every round. Both versions passed 1269/1269 correctness tests. These results suggest keeping the existing switch point on the tensor path for this PR. @forforever73 this seems relevant to selecting the tile and switch point together in your table approach, since the tensor path needs separate consideration. WDYT? |
|
@masterFoad Sorry for the late reply. I’ve opened a draft PR with some initial work here #29743. Feel free to test it on M5 and continue the work there ! |
|
@ggerganov @discobot I am new to llama.cpp but I want to contribute to this project, hence I tested the branch used in this PR on my apple M3. can anyone please let me know why tensor API is disabled on devices prior to M5. I can say this because I am getting following displayed on my console when I test the MUL_MAT operator on my M3
EDIT: Please ignore above message as I compiled the llama.ccp again on my apply M3 using following commands:
and then tested MUL_MAT operator and all of the tests passed for MUL_MAT on apple backend. command used to test MUL_MAT is following:
|
|
This should be superseded by #29869 We can do follow-up improvements from master. |
Overview
mat-mv kernels are compute-bound and scale ~linearly with the batch size, while the 64x32 mul_mm tile zero-pads 75% of the batch dimension at bs = 8.
Route q4_0 x f32 to a 64x8 tile for bs 5..16:
bs = 1 decode unaffected
Performance (M4 Pro 64GB)
test-backend-ops perf, MUL_MAT q4_0 x f32, 4096x14336:
llama-bench, gemma-4-26B-A4B q4_0: pp5 -8%, pp8 -19%, pp13 -8%, tg unchanged.
Correctness
test-backend-ops -o MUL_MAT -b MTL0: 1134/1134 vs CPU (includes q4_0 at bs 2..16 routed through the new kernel).
Additional information
Closes #25250
this problem encountered in #24768
Only tested on M4 Pro.
Requirements