Better strategy for GPU offload#520
Conversation
|
Looks good for setups like mine where PCIe bandwidth is low and prompt length is short. 128gb ddr4 3200 2ch For an existing context of 1400 + added prompt of 34 tokens, the difference was waiting a mere 3 seconds instead of 23 seconds until the first tokens: PR build: cdcb324 (3743):
Main, note the very low speeds for pp32 to pp256 build: 3f54b49 (3742):
|
|
A also took the liberty to plot @quasar-of-mikus's data: We see that in this case the performance at 512 tokens is better on the main branch. With the default value of |
|
On my setup and with this model, a lower value of
|
Sweep dopo MTP A/B (commit b17c3484): experiments: - exp_runner.ps1: generic A/B server harness for sampler/spec/quant runs - -rtr CUDA R4 trap RESOLVED post PR ikawrakow#461 (no longer catastrophic on hybrid CPU+GPU + k-quants; flat to slightly positive on Q5_K_M) - top_n_sigma=1.0 on Gemma-4 26B-A4B: +45% tg on cold cache, warm-cache neutral (1 sample/cell; accuracy not yet measured) - PR ikawrakow#520 offload threshold: default GGML_CUDA_MIN_BATCH_OFFLOAD=32 already optimal for Qwen3.6-A3B (8/128 experts) at -b 2048 -ub 2048 new models scored on coding_benchmark.py (8 tasks): - Granite-4.1-8B Q4_K_M: 51/51 in 21.85s (VALID) - replacement candidate for Granite-3.2-8B; hybrid Mamba/SSM arch is slower (pp 349 vs 791) - Qwen3-8B-Claude-Sonnet-distill: 43/45 in 150s (slow CoT) - Qwen3.5-4B: 38/43 in 103.7s (thinking-mode bench-incompatible) - Phi-4-mini-instruct: 27/31 in 11.4s; raw pp 1028 / tg 68.8 is fastest ever but 3 task syntax errors -> not usable for coding Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sweep dopo MTP A/B (commit b17c3484): experiments: - exp_runner.ps1: generic A/B server harness for sampler/spec/quant runs - -rtr CUDA R4 trap RESOLVED post PR ikawrakow#461 (no longer catastrophic on hybrid CPU+GPU + k-quants; flat to slightly positive on Q5_K_M) - top_n_sigma=1.0 on Gemma-4 26B-A4B: +45% tg on cold cache, warm-cache neutral (1 sample/cell; accuracy not yet measured) - PR ikawrakow#520 offload threshold: default GGML_CUDA_MIN_BATCH_OFFLOAD=32 already optimal for Qwen3.6-A3B (8/128 experts) at -b 2048 -ub 2048 new models scored on coding_benchmark.py (8 tasks): - Granite-4.1-8B Q4_K_M: 51/51 in 21.85s (VALID) - replacement candidate for Granite-3.2-8B; hybrid Mamba/SSM arch is slower (pp 349 vs 791) - Qwen3-8B-Claude-Sonnet-distill: 43/45 in 150s (slow CoT) - Qwen3.5-4B: 38/43 in 103.7s (thinking-mode bench-incompatible) - Phi-4-mini-instruct: 27/31 in 11.4s; raw pp 1028 / tg 68.8 is fastest ever but 3 task syntax errors -> not usable for coding Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


In a hybrid GPU/CPU situation, the decision if to offload model weights residing in RAM to the GPU to perform matrix multiplications is a tricky business. On the master branch (and also in mainline
llama.cpp) a simply heuristics is used: if the batch size is>= 32and the operation is supported, it is offloaded to the GPU. This heuristics comes from the experience with dense models (but even then, the correct decision will depend on the speed of the CPU, the GPU, and the PCI-E bandwidth).This heuristics is definitely not meaningful for MoE models. In a MoE model with$N_{\rm tot}$ total routed experts and $N_A$ active experts, the matrix multiplication for each expert will contain, on average, $N_A/N_{\rm tot} N_b$ tokens, where $N_b$ is the batch (or rather, u-batch, size). For a model such as DeepSeek-R1/V3 with $N_A = 8, N_{\rm tot} = 256$ , a batch size of 32 will result in a single token per expert on average, so offloading gigabytes of data to the GPU does not make sense at all.
This PR adds the above consideration. MoE matrix multiplications will only be offloaded if
where$N_{\rm min}$ is the minimum batch size for dense models (hard-coded to 32 on the main branch). To allow for setup/model specific adjustment, a compile time option is added that allows to change $N_{\rm min}$ via
The default value for$\ge 1024$ . For Qwen3-235B-A22B the minimumbtach size for offload becomes 512 tokens.
GGML_CUDA_MIN_BATCH_OFFLOADis left at 32. With this, MoE matrix multiplications will not get offloaded for DeepSeelk-R1/V3 unless the batch size isAs a reminder, in addition to this PR in
ik_llama.cppGPU offload can be disabled via-op 26,0,27,0,29,0.As a quick example, the following tables contain
llama-benchresults forPP-4096usingIQ4_KSquantized DeepSeek-Lite, with all experts left on the CPU.On the main branch we get this:
With this PR we get this:
We see massively better performance for small u-batch
sizes (important for a more fluid interaction with the LLM as not all prompts are so long). For this model offload kicks in at64/6*32 = 341` tokens, so for batch sizes of 512 and above the two results are the same.If I change
GGML_CUDA_MIN_BATCH_OFFLOADto 64, min batch size for offload becomes 682 tokens, and we get this result:We see that for my setup, even batches of 512 tokens are better left on the CPU (for this specific quantization type).
Please play with this PR and let me know if it is useful to get merged.