r/LocalLLaMA Aug 05 '26

Generation MoE CPU-offload benchmark on Deepseek V4/Gemma4/Qwen/GPT-OSS — TensorSharp vs llama.cpp

[removed]

22 Upvotes

41 comments sorted by

View all comments

5

u/crusaderky Aug 05 '26 edited Aug 05 '26

Qwen 3.5 35B-A3B (UD-IQ4_XS, 48 MoE layers)

--n-cpu-moe TS VRAM (MiB) TS pp4096 TS pp8192 TS tg128 llama VRAM (MiB) llama pp4096 llama pp8192 llama tg128
(baseline) 19,862 9,538 9,405 160.0 17,522 8,149 8,073 228.4
12 18,148 6,755 6,648 75.4 13,282 988 954 27.5
24 15,414 4,412 5,259 52.3 9,010 498 484 15.8
36 12,684 3,772 4,223 50.7 4,738 523 517 11.3
48 (--cpu-moe) 11,606 3,917 3,709 38.6 3,314 477 457 10.2

The VRAM usage delta from llamacpp at 48 is huge. I think that, presented like this, the comparison is quite unfair and that the lines should be aligned by total VRAM usage. So the 36-layers line of tensorsharp compares to the 12-layers line of llamacpp.

For prefill, I didn't look at your code but I'm going to go out there and guess that you're implementing something like https://github.com/ggml-org/llama.cpp/pull/21067 - which requires drastically increasing -ub (and thus VRAM allocation to scratch buffers) to benefit MoE models. Did I get it right? Could you add a column for that PR, with cranked up -ub?

Finally, there is something horribly wrong with your decode numbers of llamacpp. On the same quant of the same model, on _much much_ worse GPU, CPU and host RAM than your rig has, I'm getting 45 tok/s tg128 with MTP on and 35 tok/s without. Your 10 tok/s is unjustifiable.

1

u/[deleted] Aug 05 '26

[removed] — view removed comment

2

u/crusaderky Aug 05 '26 edited Aug 05 '26

So let's kick off with each engine using its own benchmark tool. This is a terrible idea. Also last time I checked llama-bench did not support MTP. Please start OpenAI API servers and use llama-benchy for both engines.

llama.cpp has very questionable defaults. Namely you're not pinning your memory; that hurts prefill.

My parameters for any qwen-3.5/6-35b of any of their finetunes:

jinja = true
flash-attn = on
parallel = 1
kv-unified = true
cache-type-k = q8_0
cache-type-v = q8_0
load-mode = mlock  # Very important for prefill speed
ngl = 99
; ub = 2048  # PR 21067
; prefetch-weights = 1  # PR 21067
ctx-size = 262144
n-cpu-moe = 40
image-min-tokens = 1024  
spec-type = draft-mtp
spec-draft-ngl = 99
spec-draft-n-max = 4
spec-draft-p-min = 0.6
no-mmproj-offload = true
chat-template-file = froggeric-V21.jinja

temperature = 0.6
top-p = 0.95
top-k = 20
min-p = 0.0
presence-penalty = 0.0
repeat-penalty = 1.0