- /
-
- Blog /
- Switching LLamacpp to tensor split mode
Switching LLamacpp to tensor split mode
And almost doubling the performance (3 minutes read)
2026-06-12
Primarily, I got a dual GPU setup to fit bigger models, and after that was working well enough, I got an itch to see if I could improve utilization. I had that working for a while, and it made me wonder if both GPUs could be utilized more instead of handing the baton to each one after each layer finishes.
As of now, each GPU is not even utilized at 50% most of the time:
And this is the performance (the baseline for this experiment):
llama-bench -hf unsloth/gemma-4-31B-it-qat-GGUF:UD-Q4_K_XL --split-mode layer -n 512 -d 8192,32768,65536,131072
| model | size | params | backend | ngl | test | t/s |
|---|---|---|---|---|---|---|
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | pp512 @ d8192 | 827.57 ± 4.16 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tg512 @ d8192 | 20.89 ± 0.00 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | pp512 @ d32768 | 552.09 ± 1.33 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tg512 @ d32768 | 18.94 ± 0.00 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | pp512 @ d65536 | 382.28 ± 0.64 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tg512 @ d65536 | 17.25 ± 0.00 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | pp512 @ d131072 | 236.46 ± 0.21 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tg512 @ d131072 | 13.95 ± 0.00 |
But after switching to --split-mode tensor, I got almost 100% GPU utilization, and almost double inference speeds as well:
llama-bench -hf unsloth/gemma-4-31B-it-qat-GGUF:UD-Q4_K_XL --split-mode tensor -n 512 -d 8192,32768,65536,131072
| model | size | params | backend | ngl | sm | test | t/s |
|---|---|---|---|---|---|---|---|
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | pp512 @ d8192 | 973.03 ± 18.59 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | tg512 @ d8192 | 36.12 ± 0.06 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | pp512 @ d32768 | 769.23 ± 12.14 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | tg512 @ d32768 | 32.98 ± 0.04 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | pp512 @ d65536 | 603.22 ± 7.29 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | tg512 @ d65536 | 30.44 ± 0.04 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | pp512 @ d131072 | 420.75 ± 3.54 |
| gemma4 31B Q4_0 | 16.09 GiB | 30.70 B | CUDA | -1 | tensor | tg512 @ d131072 | 25.11 ± 0.03 |
Which is around a 1.8x improvement over the layer baseline across all context windows I was intending to use.
When compiling llamacpp, I got a warning that: NCCL not found, performance for multiple CUDA GPUs will be suboptimal. However, from my perspective in my specific setup, this performs much better than using the dedicated multi GPU library.
From now on, I will be using --split-mode tensor as the default.
References
- Hugging Face gemma-4-31B-it-GGUF
- Ollama gemma4
- llamacpp GitHub
- llamacpp server readme
- llamacpp split modes
- Gemma 4 QAT release
- QAT quantization aware training
- Quantization aware training for LLMs
- CUDA Compute Capabilities table
- CUDA SDK toolkit download page
- UD - Unsloth Dynamic
- NVIDIA Collective Communication Library (NCCL)
- Perplexity

