Salut les amis !
Souvenez-vous, il y a 3 jours j’écrivais un post intitulé “Why DFlash on Qwen3.6-27B doesn’t fit on 24GB single GPU”. Mon raisonnement tenait : math VRAM serrée pour le path stock vLLM, pas de drafter quantizé public, fork llama.cpp non testé sur Blackwell consumer (j’avais bien noté que Lucebox tournait déjà DFlash sur RTX 3090 24 Go à 78 t/s, mais sans Docker public ni support sm_120 testé). Spoiler, comme on dit. Aujourd’hui, j’ai fait tourner DFlash sur mon Olares One (RTX 5090 Laptop 24 Go sm_120 Blackwell) à 80 t/s avg sur Qwen3.6-27B via une route différente. Voilà comment ça s’est passé.
Le post initial : “ça ne tient pas”
Petit rappel des ingrédients de l’échec annoncé :
- Drafter z-lab BF16 : 6 GiB. Trop gros sur 24 Go après le target.
- Pas de quantization publiée par z-lab.
- Fork buun-llama-cpp : non testé sur consumer Blackwell, perfs inconnues.
Conclusion à l’époque : “DFlash sur 24 Go consumer = impossible avec les paths publics actuels (Q1 2026)”.
Trois jours plus tard, ces trois ingrédients ont changé sous mes yeux.
Changement n°1 : un drafter quantizé GGUF est apparu
Le 28 avril, spiritbuun publie sur HuggingFace spiritbuun/Qwen3.6-27B-DFlash-GGUF :
dflash-draft-3.6-q8_0.gguf— 1,75 Go (vs 6 GiB BF16)dflash-draft-3.6-q4_k_m.gguf— 1,03 Go
D’un coup, la math VRAM tient :
| Composant | Taille |
|---|---|
| Target Qwen3.6-27B Q4_K_M | 16,8 GB |
| Drafter Q8_0 | 1,75 GB |
| KV cache @ 32K (FP16) | ~2 GB |
| Buffers + cudagraph | ~1,7 GB |
| Total | ~22,3 GB → tient sur 24 |
Bingo. Mais le drafter seul ne fait rien. Il faut un moteur d’inférence qui sait DFlash.
Changement n°2 : tester buun-llama-cpp pour de vrai
Le fork buun-llama-cpp (par spiritbuun aussi) ajoute le support --spec-type dflash à llama.cpp standard. Donc je build l’image Docker pour Blackwell consumer (-DCMAKE_CUDA_ARCHITECTURES=120 -DGGML_CUDA_NO_VMM=ON -Wl,-rpath-link,/usr/local/cuda/lib64/stubs). 2h30 de cross-compile sur OrbStack. Image aamsellem/buun-llama-cpp-dflash:0.1.0. Je deploy sur Olares One.
Premier bench, le 30 avril :
Run 1: 800 tok in 235s = 3,40 t/s
Run 2: 800 tok in 525s = 1,52 t/s
Run 3: 800 tok in 824s = 0,97 t/s
Aïe. 3,4 t/s qui dégrade jusqu’à 0,97. C’est 25× plus lent que vLLM Turbo (88 t/s) sur la même carte. Catastrophique. Les logs montrent un cycle DFlash à 1860ms par batch dont 1521ms de verify, alors que ça devrait être 15-25ms. Les kernels custom ne sont visiblement pas tunés pour sm_120.
Je file un issue #35 sur buun-llama-cpp avec tous les chiffres et la repro complète.
Changement n°3 : spiritbuun fixe le bug en 24 heures
Le 1er mai, spiritbuun répond :
“I think this may be fixed now - can you repull and give it another try?”
Entre temps, 8 commits sur master :
cab1fb597:dflash: add p_min confidence threshold + adaptive draft length← le fix probable905483277:--no-fused-gdnflag debug115995e41: disable fused GDN kernels on non-CUDA backends- merge upstream llama.cpp/master (325 commits Apr 5 → Apr 30)
Je rebuild. 2h de cross-compile encore. Tag : aamsellem/buun-llama-cpp-dflash:0.2.0. Re-deploy sur Olares One. Re-bench Space Invaders × 3.
Le résultat
Run 1: 800 tok in 10,82s = 73,94 t/s
Run 2: 800 tok in 9,96s = 80,31 t/s
Run 3: 800 tok in 9,41s = 85,06 t/s
AVG ~80 t/s [74-85 range].
+2300% vs v0.1.0. 80× plus rapide en 4 jours. Le passage de 0,97 t/s à 85 t/s tient en un seul commit upstream. C’est ça l’écosystème open source en 2026 — ça bouge à la semaine.
Comparaison sur Olares One
| Backend | Stack | t/s avg |
|---|---|---|
| llama.cpp standard | UD-Q4_K_XL, pas de spec decoding | 33-36 |
| vLLM Turbo | v0.20.0 + Genesis + TurboQuant K8V4 + MTP n=3 | 88 |
| buun-llama-cpp DFlash | HEAD aecbbd5d + Q8_0 GGUF drafter | 80 |
| vLLM vanilla (autre app) | 0.19.1 + AutoRound INT4 + MTP n=3 | 99 peak |
DFlash arrive dans la cour des champions. Pas premier en absolu (vLLM Turbo reste devant à 88), et pas le premier sur 24 Go consumer non plus — Lucebox a publié il y a quelques semaines des chiffres DFlash sur RTX 3090 24 Go (sm_86 Ampere) : 78 t/s HumanEval, 70 t/s Math500, 60 t/s GSM8K. Notre 80 t/s sur Olares One se situe dans le même range, sur la même classe de modèle.
Ce qui est nouveau ici par rapport à Lucebox 3090 :
- Hardware sm_120 Blackwell consumer au lieu de sm_86 Ampere
- RTX 5090 Laptop (mobile) au lieu de desktop
- Stack buun-llama-cpp + drafter Q8_0 GGUF spiritbuun au lieu du moteur custom Lucebox + drafter BF16 z-lab
- Reproduction publique du fix suite au filing d’issue + bench
À ma connaissance, PR #86 de Lucebox (4 mai 2026) annonce 218 t/s sur RTX 5090 desktop 32 Go via leur path — record absolu sur Blackwell — mais leur HTTP server n’est pas encore en place et leur engine ne charge pas le drafter GGUF spiritbuun.
La config qui marche
Image : aamsellem/buun-llama-cpp-dflash:0.2.0 (CUDA 13.1, sm_120 native, NO_VMM, libcuda stub link)
Args llama-server :
--model Qwen3.6-27B-Q4_K_M.gguf
--model-draft dflash-draft-3.6-q8_0.gguf
--spec-type dflash
--n-gpu-layers 99
--n-gpu-layers-draft 99
--ctx-size 32000
--ctx-size-draft 256
--batch-size 256 --ubatch-size 64
--parallel 1 --flash-attn on --jinja
--chat-template-kwargs '{"enable_thinking": false}'
Note : pour gagner ~1,8× supplémentaire selon spiritbuun, désactivez le thinking. Le drafter n’a pas été entraîné sur la distribution avec balises <think> — donc l’acceptance s’effondre quand on laisse le modèle les émettre.
Ce qu’on n’a pas (encore) testé pour pousser à 100+ t/s
- DDTree budget tuning — Lucebox sur RTX 5090 desktop tape 218 t/s à budget 22. Le défaut sous-utilise. À tester.
--no-fused-gdnON vs OFF — les kernels GDN fusés peuvent encore avoir des soucis sur sm_120.p_minadaptive draft length — le sweet spot dépend du prompt, faudrait sweep.- Context plus large — 32K conservatif. 80K devrait tenir.
Bonus : PFlash, l’autre moitié du problème
Pendant que je publiais ce post, sandropuppo (auteur Lucebox) a posté sur r/LocalLLaMA une autre release : PFlash. C’est l’inverse de DFlash :
- DFlash = decode 2-3× plus rapide (ce qu’on vient de tester)
- PFlash = prefill 10× plus rapide à 128K (24,8 s TTFT vs 257 s vanilla llama.cpp sur RTX 3090)
Le truc est que sur Qwen3.6-27B Q4_K_M, le decode est rapide (74 t/s avec DFlash sur 3090, 80 t/s sur notre 5090M) mais le prefill scale en O(S²). Sur un prompt de 131K tokens, vanilla llama.cpp prend 4 minutes avant le premier token. Aïe. Décode rapide = inutile si tu attends 4 minutes à chaque message.
PFlash combine Speculative Prefill (arXiv 2502.02789) + FlashPrefill + Block-Sparse-Attention pour scorer les tokens importants via un mini-drafter Qwen3-0.6B et ne prefill que les spans qui comptent. C++/CUDA pur, pas de Python, in-process avec DFlash.
PFlash est mergé dans le repo Lucebox aujourd’hui même (4 mai) — pas encore dans notre image v1.2.0. Prochain rebuild on l’ajoute. La combinaison DFlash + PFlash sur sm_120 c’est potentiellement le top du top sur consumer 24 Go : décode rapide ET premier token rapide même sur prompts de 128K.
À tester très bientôt.
TL;DR
Le path stock DFlash sur 24 Go consumer Blackwell mobile n’est plus impossible. 80 t/s avg sur Qwen3.6-27B avec :
- spiritbuun/Qwen3.6-27B-DFlash-GGUF Q8_0 (1,75 Go)
- spiritbuun/buun-llama-cpp HEAD compilé pour sm_120
Mon post du 28 avril qui disait “impossible” pour le path stock vLLM/llama.cpp est désormais obsolète depuis le 1er mai. La leçon : en 2026 sur l’écosystème LLM consumer, “impossible” a une demi-vie de 72 heures.
Crédits
- spiritbuun pour le fork llama.cpp avec DFlash + le drafter GGUF + le fix express après mon issue #35
- z-lab/dflash pour la méthode Block Diffusion drafter
- unsloth pour le Qwen3.6-27B Q4_K_M GGUF
- Lucebox pour le bench RTX 5090 desktop qui prouvait que sm_120 pouvait y arriver
Voilà ! Si vous tournez sur 5090M, 4080M, 3090 ou 4090 24 Go et que vous reproduisez ces chiffres (ou battez 100+ t/s avec un tweak DDTree), envoyez-moi vos résultats. À 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.