cuda: tune the mmvq/mmq crossover for Turing

Turing had no entry in ggml_cuda_should_use_mmvq and fell through to the
generic ne11 <= 8, while Ada, Blackwell, DGX Spark and Orin all have measured
switch points. MMQ overtakes MMVQ far earlier than n=8 on SM75.

Measured on a CMP 50HX (cc 7.5, CUDA 13.3) with test-backend-ops perf, medians
of 4 reps after a discarded warmup, forcing each path via an instrumentation
build. MMQ speedup over MMVQ at n=8:

  q2_K 2.57x   q3_K 2.13x   q4_K 1.96x   iq4_xs 1.93x   q5_K 1.79x   q6_K 1.74x

End to end on Qwen3.5-9B-UD-Q4_K_XL, llama-bench, medians of 3 interleaved
rounds at -r 20:

  pp1 -0.2%   pp2 0.0%   pp3 0.0%   pp4 +3.2%   pp5 +12.1%   pp8 +47.6%

q6_K is deliberately 3 rather than the 2 the synthetic sweep suggested. That
sweep had a single shape for q6_K and MMQ won it by only 1.02x, the weakest
margin measured. With the threshold at 2 the model regressed 2% at pp3,
reproducibly across three rounds: its 24 q6_K tensors were the only ones
switching path at that batch size. The synthetic margin did not survive on the
model's real q6_K shapes, so mmvq keeps n=3 for that type.

q4_K was measured across five m/k shapes; at n=3 mmvq wins 1.19x/1.09x/1.08x on
three and loses 1.01x on two, geometric mean 1.065 in mmvq's favour. At n=4 mmq
wins on all five.

The n=512 cases act as a control: above MMVQ_MAX_BATCH_SIZE neither mode can
select mmvq, and both measure within 1.00x-1.01x of each other.

Only the measured types are listed; everything else keeps the default. q2_K and
q3_K rest on a single shape each and are not present in the model used for the
end-to-end check, so they are less well evidenced than the rest.
This commit is contained in:
xrip committed 2026-09-21 20:53:22 +03:00
1 parent 6f65493dde
commit 85ff4657cb
1 file changed
+19
+19
View File
@@ -367,6 +367,25 @@ bool ggml_cuda_should_use_mmvq(enum ggml_type type, int cc, int64_t ne11) {
return ne11 <= MMVQ_MAX_BATCH_SIZE;
}
}
if (GGML_CUDA_CC_IS_NVIDIA(cc) && cc == GGML_CUDA_CC_TURING) {
// Tuned on a CMP 50HX. Turing had no entry here and fell through to
// ne11 <= 8, but MMQ overtakes MMVQ much earlier than that: by n=8 it
// is 1.7x-2.6x faster depending on the type. Only the types measured
// are listed; the rest keep the default.
switch (type) {
case GGML_TYPE_Q2_K:
case GGML_TYPE_Q3_K:
return ne11 <= 2;
case GGML_TYPE_Q4_K:
case GGML_TYPE_Q5_K:
case GGML_TYPE_Q6_K:
case GGML_TYPE_IQ4_XS:
return ne11 <= 3;
default:
return ne11 <= MMVQ_MAX_BATCH_SIZE;
}
}
if (GGML_CUDA_CC_IS_NVIDIA(cc) && cc == GGML_CUDA_CC_VOLTA) {
switch (type) {
case GGML_TYPE_Q2_K: