Skip to content
/ airelien.dev
Go back
Aurélien AMSELLEM

Gemma 4 26B-A4B + DFlash sur RTX 5090 Laptop 24 Go — n_spec=8 optimal, +5% vs default, et un cycle de dégradation chelou

Sweep complet de num_speculative_tokens pour Gemma 4 26B-A4B + drafter DFlash z-lab sur RTX 5090M (24 Go sm_120). Optimal = n_spec=8 (pas n=15 comme en desktop). J'ai aussi trouvé un cycle de dégradation 100% reproductible que j'ai pas réussi à fixer côté config.

Salut les amis ! Suite de mon aventure sur le DFlash de Gemma 4 sur Olares One : la dernière fois j’avais sorti 214 t/s steady en bench Space Invaders avec n_spec=13 sur le RTX 5090 Laptop 24 Go. Puis Tech-Practice a publié un sweep complet sur le desktop 5090 32 Go qui montre 228 → 600 t/s à n_spec=15. Naturellement je me suis dit : est-ce que n=15 gagne aussi en mobile ?

Eh ben non. C’est n_spec=8 qui gagne sur le 5090M, avec un peak à ~235 t/s et un stable autour de 224 t/s — environ +5% sur mon default précédent à n=13. Et j’ai trouvé un truc encore plus chelou en validant : un cycle de dégradation 100% reproductible toutes les 9-10 requêtes, que j’ai pas réussi à fixer côté config.

TL;DR

Shippé en vllmgemma4dflashone v1.0.4 dans orales-one-market.

Le matos

La stack

La méthodo

Le prompt standard Space Invaders HTML, 2000 tokens, temp=0.6, top_p=0.95. 2 warmups + 3 à 10 runs mesurés selon le point. Le bench harness tourne dans le pod via kubectl exec pour bypasser le sidecar Envoy.

Le sweep

n_specAVG stableMAXn_runs
6220.61225.955
8223.90235.225
10~215222.073
11212.25217.665
12~202206.803
13 (était v1.0.0)~207213.275
15 (reco Tech-Practice)201.39211.273
17~194195.763
20187.33196.123
n=6:   ████████████████████████████████  220.61
n=8:   █████████████████████████████████ 223.90  ← peak
n=10:  ████████████████████████████████  ~215
n=11:  ██████████████████████████████    212.25
n=12:  ██████████████████████████        ~202
n=13:  ████████████████████████████      ~207
n=15:  █████████████████████████         201.39
n=17:  ████████████████████              ~194
n=20:  ██████████████                    187.33

Le peak est sans ambiguïté à n=8. Plus profond (n=15+) coûte ~15% ; plus shallow (n=6) rend ~1,5%.

Pourquoi n=8 en mobile et n=15 en desktop

Deux contraintes poussent le mobile vers des drafts plus shallow :

  1. Bande passante mémoire : 896 Go/s vs 1,79 To/s. Chaque token spéculatif dans le draft demande des lectures KV supplémentaires pour la passe de vérification du target. Des drafts plus profonds saturent le bus mémoire.
  2. Budget VRAM : 24 Go vs 32 Go. Les compute buffers du pipeline spec scalent avec n_spec. À n=15, j’avais déjà eu un OOM en cudagraph_capture quand j’avais bump max-num-batched-tokens à 32768.

Le desktop a ~33% de VRAM en plus et ~100% de bande passante en plus — les deux favorisent des drafts plus profonds. En mobile, n_spec=8 c’est le point Pareto-optimal : assez profond pour que le draft amortisse le coût du verify, assez shallow pour que les compute buffers tiennent confortablement.

La partie chelou : un cycle de dégradation reproductible

Quand j’ai étendu le bench n=8 à 10 runs (au lieu de 3) pour valider, j’ai vu ça :

run1  : 221 t/s ← fast (DFlash actif)
run2  : 214 t/s
run3  : 218 t/s
run4  : 222 t/s
run5  : 230 t/s
run6  : 103 t/s ← transition
run7  :  59 t/s ← DÉGRADÉ (pas de spec decoding)
run8  :  62 t/s
run9  :  62 t/s
run10 : 212 t/s ← récupéré

Exactement 5 fast, 1 transition, 3 dégradés, 1 recovery. Reproductible sur plusieurs boots de pod. Le 60 t/s correspond à ce qu’on attendrait de Gemma 4 26B-A4B en decode vanille SANS spec — DFlash est désactivé temporairement par quelque chose dans le pipeline vLLM.

J’ai testé quatre workarounds :

J’ai aussi tenté de swap l’image vLLM vers cu130-nightly-x86_64 (vLLM 0.19.2) et vllm/vllm-openai:gemma4 (vLLM 0.18.2) — toutes les deux plus anciennes que le tokenspeed-preview que j’utilise (vLLM 0.20.2), donc aucune ne supporte ma combo DFlash + Gemma 4 + triton_attn (l’une erreur avec “non-causal attention not supported”, l’autre n’a même pas DFlash enregistré pour gemma4_text).

Du coup je peux pas tester les PRs récents de hardening Gemma 4 DFlash (#41703, #42102, #40898) sans build une image vLLM custom from main — hors scope pour ce soir.

Mon hypothèse : low-yield spec fallback

Le cycle est trop déterministe pour être du thermal GPU (la carte reste à ~70 °C). Au début je suspectais une re-capture de cudagraph ou une défrag KV, mais en triant les PRs llama.cpp j’ai trouvé une PR closed — #22931 “adaptive low-yield MTP fallback” de leon7609 — qui matche bien mieux.

Cette PR documente le même pattern pathologique sur DeepSeek V4 dans llama.cpp :

Mon modèle actuel :

  1. z-lab/gemma-4-26B-A4B-it-DFlash a une acceptance bruitée — confirmé dans mon premier bench Gemma 4 DFlash où l’acceptance pos-0 du drafter était seulement ~28% (bien plus bas que les ~60% typiques pour DFlash sur ses targets tunés).
  2. Après une série de ~5 requêtes avec accept chanceux, l’état KV du drafter diverge assez du target pour que l’acceptance s’effondre temporairement pour les ~4 requêtes suivantes.
  3. Pendant que l’acceptance est effondrée, l’amplification verify 4.7× produit les ~60 t/s observés.
  4. Après assez de drafts rejetés, l’état interne du drafter reset et l’acceptance récupère.

Si cette hypothèse est correcte, le fix n’est pas dans vLLM — il est dans l’alignement du drafter. Soit z-lab ship un drafter DFlash mieux aligné pour Gemma 4 (finetuné plus agressivement sur la distribution de sortie du target), soit on accepte le cycle comme une propriété de “DFlash off-the-shelf sur Gemma 4” jusqu’à ce qu’un drafter Gemma 4-specific entraîné conjointement avec le target débarque.

J’aimerais beaucoup un deuxième reproducer de quelqu’un qui run la même stack — si vous confirmez le pattern 5-fast/4-slow avec z-lab/gemma-4-26B-A4B-it-DFlash, pingez-moi et j’ouvre un issue upstream propre avec deux repros indépendants.

Impact réel : mon AVG sur long session de 10 requêtes est ~161 t/s au lieu du 224 t/s peak. En milieu de session, ponctuellement une requête va prendre 30 secondes au lieu de 9 — gênant pour n’importe quel workflow agentique qui streame des tokens.

Ce qui ship dans vllmgemma4dflashone v1.0.4

Le chart Olares Market, un seul diff de config vs v1.0.0 :

SPEC_CONFIG: '{"method":"dflash","model":"z-lab/gemma-4-26B-A4B-it-DFlash","num_speculative_tokens":8}'

Le --attention-backend triton_attn était déjà auto-sélectionné implicitement par vLLM ; je l’ai juste rendu explicite. Le reste (KV fp8, max-num-seqs 4, prefix-caching on) reste inchangé.

Bonus : Gemma 4 Audio One

Pendant que les cycles de bench tournaient, j’ai aussi shippé une nouvelle app : llamacppgemma4audione v1.0.0. Elle utilise la PR llama.cpp #21421 (encoder USM Conformer pour l’input audio Gemma 4, mergée le 12 avril — déjà dans b9101) avec unsloth/gemma-4-E4B-it-GGUF Q4_K_M + le mmproj BF16 (les mmproj F16 et Q8_0 produisent de la sortie répétitive — seul le BF16 marche à cause de la sensibilité numérique des couches ClippableLinear).

~6 Go de VRAM, max 30 secondes d’audio par input, OpenAI-compat chat completions avec content type input_audio. ASR, audio understanding, couche d’input pour agent vocal. Assez léger pour cohabiter avec une autre app GPU.

Reproductible

Chart Helm complet, tag d’image exact, tous les flags, harness de bench — tout est dans orales-one-market. Comme promis sur la home : chaque chiffre ici vient avec la stack exacte pour le reproduire.

Si vous tournez Gemma 4 + DFlash sur du Blackwell consumer (5090M, 5070 Ti, 5080) et que vous voyez le même cycle, pingez-moi — je file le bug upstream vLLM dès que j’ai un deuxième reproducer indépendant.

Share this post on:

Commentaires