Salut les amis !
Hier soir sur r/LocalLLaMA, u/ilintar annonce que la PR MTP de am17an passe en beta. 334 upvotes en quelques heures. Le tweet final : “expect most performance gaps between llama.cpp and vLLM… to be erased.”
Spoiler : sur ma machine, baseline llama.cpp = 35 t/s. Avec PR #22673 + le bon GGUF MTP : 78 t/s. +123%. Sans toucher à Genesis, à Lucebox, à HAMi. Voilà comment.
Le contexte : MTP était dans vLLM, pas dans llama.cpp
Multi-Token Prediction est une technique de speculative decoding où le modèle apprend à prédire plusieurs tokens en avant dans une seule forward pass. Au moment de servir, on utilise ces prédictions comme “draft” gratuit : le modèle vérifie en parallèle, accepte les bons, jette les mauvais. Si l’acceptance est bonne, c’est ~2× plus rapide.
Qwen a entraîné Qwen3.6 avec une tête MTP intégrée. vLLM sait l’utiliser depuis longtemps (--speculative-config '{"method":"mtp","num_speculative_tokens":3}'). llama.cpp ne savait pas — jusqu’à la PR #22673 d’Aman Gupta, ouverte le 4 mai 2026.
La PR ajoute :
- Une classe
mtpau menu--spec-type - Le pipeline qui partage les hidden states entre target et MTP head
- Le support du modèle Qwen3.6 27B et 35B-A3B
Aman teste sur DGX Spark. Communauté Reddit teste rapidement :
- alexandrupetraru : Strix Halo Qwen3.6-35B-A3B q8 → 40 → 70 tg/s (+75%)
- GloballyUniquePlaceholder : 3060 Laptop 6 Go + 64 Go RAM → speedup réel
- superjamie : 3× RTX 3060 testé OK avec
RDson/Qwen3.6-27B-MTP-Q4_K_M-GGUF
Pas de bench Blackwell consumer. Mon Olares One avec son RTX 5090M est le candidat.
Le build : am17an/mtp-clean + sm_120
PR #22673 vit sur la branche mtp-clean du fork am17an/llama.cpp. Cinq commits :
1a4fe4e llama: allow partial seq_rm for GDN models for spec decoding
589490f add enum for part sequence removal
c5e0227 rename rollback to rs_seq
10829db llama + spec: MTP support
f8c6b03 add qwen35moe_mtp
Plutôt que de cherry-picker dans buun-llama-cpp (mon fork DFlash habituel), je build directement depuis cette branche en mode minimal — juste llama-server pour Qwen3.6 27B + sm_120 native :
FROM nvidia/cuda:13.1.0-devel-ubuntu22.04 AS build
RUN git clone --depth 1 --branch mtp-clean \
https://github.com/am17an/llama.cpp /src/llama.cpp
WORKDIR /src/llama.cpp
RUN cmake -B build \
-DGGML_CUDA=ON -DGGML_CUDA_NO_VMM=ON \
-DCMAKE_CUDA_ARCHITECTURES=120 \
-DLLAMA_CURL=ON \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,-rpath-link,/usr/local/cuda/lib64/stubs" \
-DCMAKE_BUILD_TYPE=Release && \
cmake --build build -j$(nproc) --target llama-server
2h de cross-compile sur OrbStack Mac. Image aamsellem/llamacpp-mtp:0.1.0, 2,62 Go.
Pas de Genesis patches, pas de DFlash custom kernels, pas de Lucebox. Juste llama.cpp + une PR.
Le GGUF : RDson/Qwen3.6-27B-MTP-Q4_K_M-GGUF
Détail important : pour utiliser MTP via llama.cpp, le GGUF doit inclure la tête MTP. Le Qwen3.6-27B Q4_K_M de unsloth ne l’inclut pas (la tête MTP a été retirée à la quantization standard).
Heureusement, RDson l’a fait quantize avec ik_llama :
- Fichier unique :
Qwen3.6-27B-MTP-Q4_K_M.gguf— 16,49 Go - Tient sur 24 Go avec marge confortable
- Compatible llama.cpp PR #22673
am17an a aussi publié un Q8_0 sur sa propre repo, mais 28 Go = pas pour 24 Go.
La config llama-server
llama-server \
--model /models/Qwen3.6-27B-MTP-Q4_K_M.gguf \
--host 0.0.0.0 --port 8000 \
--n-gpu-layers 99 \
--ctx-size 32000 \
--threads 16 \
--batch-size 256 --ubatch-size 64 \
--parallel 1 \
--flash-attn on --jinja \
--spec-type mtp \
--spec-draft-n-max 4 \
--chat-template-kwargs '{"enable_thinking": false}'
Notes :
--spec-type mtp: la nouvelle option de PR #22673--spec-draft-n-max 4: USBhost sur Reddit a trouvé que 4 est le sweet spot — j’ai gardé son numéro- Pas de
--model-draft: MTP est dans le modèle, pas un drafter séparé enable_thinking: false: conseillé partout, le draft head n’a pas vu de balises<think>à l’entraînement
Le bench
Trois prompts Space Invaders, max_tokens=800, temp=0.6, top_p=0.95 :
Run 1: 800 tok in 10,68s = 74,91 t/s
Run 2: 800 tok in 9,93s = 80,60 t/s
Run 3: 800 tok in 10,15s = 78,78 t/s
AVG 78,1 t/s [74,9-80,6].
Comparaison sur la même machine (Olares One, RTX 5090M 24GB sm_120)
| Stack | t/s avg | Complexité stack |
|---|---|---|
| llama.cpp standard (sans spec) | 33-36 | upstream pur |
| llama.cpp + MTP (PR #22673) | 78,1 | upstream pur + 1 PR |
| buun-llama-cpp DFlash + Q8_0 GGUF drafter | 80 | fork llama.cpp |
| vLLM Turbo (Genesis 28 patches + TurboQuant K8V4 + MTP n=3) | 88,0 | vLLM + 28 patches + custom image |
| Lucebox v1.6.0 (PR #94 + q4_0 KV + DDTree 22) | 88,7 | engine custom + libvgpu hot-swap + 4 workarounds |
+123% MTP llama.cpp vs baseline. Plus que les +75% Strix Halo de alexandrupetraru — la 5090M a probablement plus de marge à tirer parce que le baseline est lower (bandwidth contraint plus que sm_122).
Pourquoi 78 < 88 ? Parce que MTP est plus modeste que DFlash custom
MTP donne ~2× sur la baseline (acceptance ~75% × 4 draft tokens). DFlash bien tuné (Lucebox, drafter dédié, kernels custom) donne ~2,5-3×. Au-dessus de MTP llama.cpp, on a :
- buun DFlash 80 t/s : Q8_0 GGUF drafter quantizé + spec-type dflash optimisé sm_120
- vLLM Turbo 88 t/s : Genesis 28 patches qui débloquent TurboQuant K8V4 + MTP n=3
- Lucebox 88,7 t/s : engine custom test_dflash + DDTree budget tuning
Tous ont besoin d’un fork ou de patches. MTP llama.cpp = la seule version qui sera mergée upstream dès que la PR review se complète.
Le vrai message
Dès que PR #22673 merge dans ggml-org/llama.cpp master, n’importe qui qui pull ghcr.io/ggml-org/llama.cpp:server-cudaXY-bNNNN et qui télécharge un GGUF Qwen3.6-MTP-enabled aura ~78 t/s sur consumer Blackwell mobile 24 Go, sans rien à fork.
C’est pas le record absolu (Lucebox 88,7), mais c’est :
- Reproductible : un seul
docker pull+ un seulhuggingface-cli download - Maintenable : llama.cpp upstream ne va pas casser, contrairement aux forks
- Compatible avec les outils LM Studio / Open WebUI / Ollama qui consomment llama.cpp officielle
C’est ce qui change vraiment la donne pour les utilisateurs end-user. Les forks restent la bonne réponse pour les benchmarks records ; MTP upstream sera la bonne réponse pour la distribution massive.
Pour suivre le merge
- PR https://github.com/ggml-org/llama.cpp/pull/22673
- État au 5 mai : OPEN, BLOCKED (en review). 18 commentaires, beaucoup de tests communautaires positifs.
- Quand mergé, sera dans le prochain build llama.cpp tagué (probablement b9027+)
- am17an publiera l’image officielle ou attendre
ghcr.io/ggml-org/llama.cpp:server-cuda13-bNNNNune fois sortie
Crédits
- am17an (Aman Gupta) pour la PR #22673 et le GGUF Q8_0
- u/ilintar pour avoir poussé l’annonce sur r/LocalLLaMA
- RDson pour le quant Q4_K_M MTP-enabled qui fit 24 Go
- alexandrupetraru, USBhost, superjamie, GloballyUniquePlaceholder pour les benchmarks communautaires qui ont validé la PR avant que je teste
Voilà ! Si vous tournez sur 5090M / 4080M / 3090 24 Go et que vous reproduisez ces 78 t/s (ou battez avec un sweep --spec-draft-n-max), envoyez-moi vos chiffres. À très vite !
Disclosure — Tous les benchmarks de ce post tournent sur mon propre Olares One. Si le contenu vous a été utile et que vous envisagez d’en acheter un, commander via ce lien de parrainage vous donne 400 $ de réduction (3 599 $ au lieu de 3 999 $) et me rapporte 200 $. Je le mentionne par transparence — et oui, accessoirement, ça aide à faire vivre le blog (hébergement, domaine, et le temps que je passe à écrire ici). Lien valable jusqu’à fin juin 2026 environ.