URL:     https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-llm-ia-debordement-cpu-ram-mixture-of-experts-et-benchmarks
Title:   Auto-héberger ses LLM (IA) : Débordement CPU+RAM, Mixture-of-Experts et Benchmarks
Authors: Jérôme Flesch
Date:    2026-08-03T12:55:29+02:00
License: CC By-SA
Tags:    intelligence_artificielle, llama, llama-swap, nvidia, intel, amd et grands_modèles_de_langage
Score:   5


# Introduction

Ce journal est dans le prolongement de mes précédents journaux :

- [Auto-héberger ses IA : Principes généraux](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia)
- [Auto-héberger ses IA : Matériel et optimisation de l'inférence](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia-materiel-et-optimisation-de-l-inference)

Dans ce journal, on va parler de faire de l'inférence avec des LLM, avec pas ou peu de VRAM. Autrement dit, on va essayer de faire rentrer une grosse pièce carrée dans un petit trou rond.

Comme moi, vous avez peut-être observé quelque chose d'étrange : Il y a plein de [vidéos Youtube](https://www.youtube.com/watch?v=8F_5pdcD3HY), de publications LinkedIn, etc. qui vous disent que c'est super simple de faire tourner des LLM sur une pièce de musée (genre Nvidia GTX 1060 6 Go avec de la DDR4). Ils vous expliquent que ça tournera super vite, super bien, etc. Apparemment, il faut juste trouver les paramètres magiques qui vont bien, et pouf ! Plus jamais besoin de Claude Fable 5 ! 🎉

Mais alors, pourquoi tous les développeurs ne font pas juste ça ? En plus, il y a [un mec](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia) qui l'a bien expliqué : Tous les fadas de LLM courent désespérément après les plus grosses cartes graphiques, tant qu'ils peuvent les acheter sans devoir vendre leurs enfants.

Du coup, c'est suspect, et [votre bon sens doit vous picoter pas mal](https://imgur.com/UBZpH).


# Vocabulaire

Quelques gros mots qui vont être pas mal utilisés dans ce journal :

- LLM : une IA qui génère du texte ;
- token : un bout de mot (typiquement une syllabe par exemple) ;
- le contexte : votre discussion avec votre LLM préféré ;
- le préremplissage (*prefill*) : la (re)lecture du contexte par le LLM ;
- la prédiction de tokens : la génération de mots par le LLM.


# La problématique des vitesses d'inférence

Mesurer la vitesse de la prédiction des tokens, avec un contexte presque vide, c'est trivial. N'importe quel Youtuber, influenceur LinkedIn ou autre amibe mononeuronale sait le faire, et … ne fait souvent que ça. Donc en bonne amibe bineuronale, je vais le faire aussi 😁. On va généralement considérer qu'un modèle est utilisable à partir de 10 tokens/s (c'est en fait assez optimiste, mais soyons généreux).

Et poussons les choses plus loin : Pour ce journal, mon objectif est de voir aussi, en fonction de la taille du contexte, s'il y a une dégradation des performances. Plus important encore, ce n'est pas juste la prédiction des tokens qui m'intéresse, mais aussi le préremplissage avec un contexte existant. Pour certaines utilisations, on se tape du préremplissage (simple conversation, etc.), mais pour d'autres, la vitesse de préremplissage est très importante. Quelques exemples :

- Domotique : Avec Home Assistant, si vous exposez beaucoup d'appareils au LLM, ça fait beaucoup de tokens d'outils en plus à lire au début de chaque conversation. Chez moi, 13 entités exposées impliquent un contexte initial de 2500 tokens. Or un assistant vocal doit être très réactif (passé 5 mississippis, je considère que la personne moyenne s'impatiente).
- Programmation agentique : Le début d'une session, c'est tout de suite ~8k tokens d'outils dans mon cas.
- Toujours en programmation agentique : À chaque fois que l'agent va appeler un outil, il va potentiellement se prendre une grosse sortie d'une commande ou un bout de fichier conséquent. À chaque fois, il va se prendre facilement 1000 à 10000 tokens à relire (si pas plus).
- Discussion Open-WebUI avec quelques outils activés : Le début d'une conversation, dans mon cas, c'est ~20k tokens d'entrée de jeu (oui, je l'ai chargé comme une mule \^\^).
- Résumé de document : Pour vous résumer un PDF de 100 pages (genre d'une boite de *consulting*, que votre entreprise aurait embauchée pour la conseiller de faire ce que vous aviez déjà prévu de faire), le LLM doit se taper environ 45k tokens.

Et il y a pire : Si vous avez interrompu votre conversation ou votre session de programmation agentique la veille, alors que le contexte était presque plein. Quand vous voudrez la reprendre, votre LLM va devoir se refarcir tout le contexte existant. Pour la suite, on va partir sur 64k tokens, mais gardez à l'esprit que ça peut être nettement plus.

Est-ce que vous commencez à deviner le piège dans lequel beaucoup de gens tombent ? 🧐


# Les modèles Mixture-of-Experts

Le premier truc qu'on peut remarquer, c'est que ces fameuses vidéos Youtube et autres vous invitent toujours à utiliser des LLM Mixture-of-Experts, et non pas des LLM denses.

Dans mon premier journal, je disais qu'un MoE (Mixture-of-Experts), c'est en fait un ensemble de sous-LLM spécialisés ("experts"), et c'est un 1er réseau de neurones qui décide vers quel autre LLM envoyer la requête. En fait, cette description est hyper-simplifiée. Il y a notamment une alternance entre les couches des experts et les couches d'attention. Mais dans le cadre de ce journal, on va rester sur cette vision simplifiée des modèles MoE.

Il faut savoir surtout une chose : Pour chaque LLM MoE, son développeur indique le nombre maximum de paramètres actifs simultanément (par exemple, A3B pour Qwen-3.6 35B, A10B pour Qwen-3.5 122B, A4B pour Gemma-4 26B, etc). Mais attention, on parle du nombre de paramètres actifs pour traiter **un seul token** ! D'un token à l'autre, c'est d'autres jeux d'experts/paramètres qui seront sollicités. Donc, pour traiter|générer chaque token individuellement, on gagne clairement en vitesse de calcul. Mais pour traiter un prompt ou générer toute une sortie, on doit quand même avoir l'intégralité du modèle chargé en VRAM/RAM.

![Dense](https://i.imgur.com/XrUCysS.png)

![MoE](https://i.imgur.com/qPlPTsD.png)

Sur l'exemple beaucoup trop sursimplifié ci-dessus, on parlerait d'un modèle MoE avec 36 paramètres, dont 20 actifs simultanément.

Clairement, à taille égale, les MoE sont donc bien plus rapides que les modèles denses, qui eux sollicitent l'essentiel de leurs paramètres à chaque token. Ils sollicitent aussi nettement moins la bande passante de la VRAM/RAM. Ils sont en fait si rapides que l'idée de déborder de la VRAM et d'utiliser aussi le CPU et la RAM pour en faire tourner de plus gros n'est pas forcément absurde.

Leur gros inconvénient, c'est qu'à nombre de paramètres égaux, ils sont plus bêtes que des modèles denses. Par exemple, Qwen 3.6 35B A3B est notablement plus bête que Qwen 3.6 27B.

Toutefois, on peut noter que les gros LLM (>1T) sont souvent des MoE. Cette architecture rend leur inférence nettement moins couteuse. Or, ils sont loin d'être bêtes. Ils compensent leur bêtise proportionnelle en étant énormes et en ayant un grand nombre de paramètres actifs simultanément (A40B pour GLM-5.2 par exemple). Autrement dit, un petit dense bat un plus gros MoE, mais un beaucoup plus gros MoE 💪 prend le petit dense 🖐️, le retourne 🔄, et le fume 🚬.

En plus, un très gros modèle tolère mieux la quantification qu'un petit. On peut théoriquement taper sur du très gros modèle en q2 et toujours avoir quelque chose de correct.

Et c'est là que le commentaire de [Andréas Livet](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia-materiel-et-optimisation-de-l-inference#comment-2027074) sur mon précédent journal m'a fait beaucoup trop réfléchir. Et si, pour l'auto-hébergement, j'avais sous-estimé l'utilité des MoE ? Et si ces vidéos Youtube disaient vrai ? Et si on pouvait faire tourner de façon fiable un gros MoE comme Qwen-3.5 122B sur du matériel consommateur ? Peut-être même plus gros encore ? Et où se trouve la limite ? GLM-5.2 pourrait-il fonctionner sur ma machine ? Bref, comme cette idée m'a fait bizarrement saliver 🤤, il fallait que je la teste.


# Élément de comparaison : les IA cloud

On va prendre pour référence les vitesses d'LLM cloud bien connus. Sauf que … zut, aucun ne publie de chiffres officiels (ahah, [poules mouillées](https://www.youtube.com/watch?v=tM4044Bh4FU) ! 🐤💧).

Ceci dit, la vitesse estimée de Claude Opus 4.5 en prédiction est d'environ 40 à 50 tokens/s. Je n'ai trouvé qu'une seule estimation pour le préremplissage : [~400 tokens/s](https://tokencalculator.com/tools/token-speed-calculator), mais ça me semble plutôt bas.



# Attention, benchmarks droit devant !

Soyons clairs : je déteste les benchmarks. Pourtant, dans ce journal, je vais sortir des résultats de benchmarks que j'ai faits moi-même comme un grand. Ces résultats sont juste là pour vous donner des ordres d'idée et illustrer, et n'ont absolument pas vocation à être exacts. En plus, comme vous le verrez, ils sont très dépendants de la configuration matérielle et logicielle.

De plus, les conclusions issues de ces benchmarks sont totalement subjectives. J'ai essayé d'être le plus factuel possible, mais les conclusions dépendent entièrement de vos besoins et de vos valeurs. Ce que je juge inacceptable ne l'est peut-être pas pour vous, et [vice versa](https://www.youtube.com/watch?v=ZTeqM5gciH8).

Sur ce, allons maintenant prestement casser notre CPU+RAM sur des LLM, tel le Titanic et son légendaire Iceberg.




# Méthodologie

## Matériel

Tous mes tests ont été faits sur des machines avec de la DDR4 3200 MHz.

Je n'ai jamais pu passer à la DDR5 à cause de la Ramapocalypse … (pour ceux qui vivent dans une caverne et qui n'ont pas vu le jour depuis le Covid : les prix de la DDR5 sont complètement lunaires, et [ça va probablement empirer](https://www.lesnumeriques.com/informatique/valve-est-categorique-la-ram-ne-sera-pas-a-un-prix-accessible-avant-des-annees-pour-une-raison-simple-n259448.html)). Si vous voulez comparer au doigt mouillé avec la meilleure DDR5 disponible actuellement, vous pouvez multiplier les valeurs limitées par le CPU+RAM par des facteurs de 1,5 jusqu'à 2,5. Sur un malentendu, ça tombera peut-être à peu près juste.


## Modèles

J'ai tapé dans la famille Qwen 3.5. Pour cette famille, Alibaba a développé une large variété de taille de LLM, et a fait aussi bien des denses que des MoE. Elle m'a donc semblé idéale pour illustrer ce journal.

- Les Qwen 3.5 ≤ 27B sont denses.
- Les Qwen 3.5 ≥ 35B sont MoE.

Tous ces modèles ont un contexte maximum de 256K tokens.

En plus, Qwen 3.5 27B a exactement la même architecture que mon chouchou Qwen 3.6 27B \^\^.


## MTP

Je n'ai pas MTP activé pour ces benchmarks.

D'après mon expérience personnelle, totalement subjective, et mesurée avec mes fesses, MTP aide uniquement quand le modèle est entièrement en GPU. Il n'aide pas (voir il dégrade) les performances dès que le CPU est impliqué. Donc par cohérence, je l'ai désactivé dans tous mes benchmarks.



## Mesures

J'ai préparé essentiellement des courbes de vitesses en fonction de la taille du contexte. J'ai utilisé llama-bench. Initialement, j'avais utilisé une boucle `for`, mais avant que j'aie eu le temps de comprendre ce qu'il se passe, cette boucle est devenue [un script Python cracra](https://jerome.flesch.info/blog/20260726-selfhosting-llm-overflow-and-moe/llm_benchmark.py).

Pour chaque taille de contexte/prompt, je demande à llama-bench de faire lire la-dite taille de contexte au LLM, puis de faire générer 512 tokens au LLM. À noter que llama-bench génère les tokens aléatoirement. Il ne cherche pas à faire des phrases qui ont du sens. Donc je suspecte que ça doit activer les MoE comme des sapins de Noël.

Le temps d'exécution de llama-bench pour chaque point a été limité à 2h. Cette limite explique l'absence de certains points sur certaines courbes.

Certains modèles manquent parfois entièrement sur certains graphiques. C'est parce que leurs tests ont échoué pour une raison ou une autre, et que j'ai décidé que j'avais mieux à faire que de me battre avec. Au passage, j'ai un gros soupçon qu'il y a une fuite de VRAM dans le pilote Nvidia : j'ai dû redémarrer ma machine plusieurs fois et passer certains scénarios indépendamment des autres, mais avec les mêmes réglages à chaque fois.

Pour des questions de lisibilité, les valeurs dans les tableaux sont des valeurs arrondies (généralement vers le pire). J'ai mis en gras les temps estimés qui, selon moi, ne sont pas utilisables.


# 5 cartes graphiques Nvidia RTX 3060 12Go

Avant toute chose, on va s'intéresser rapidement aux performances quand tout tourne sur des cartes graphiques optimisées aux petits oignons ([ou pas encore](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia-materiel-et-optimisation-de-l-inference#comment-2027770)).


## La prédiction

![La prédiction sur 5 GPU](https://i.imgur.com/rOnt4ZS.png)

La vitesse de prédiction (génération de tokens) est stable (divulgâchage : elle est toujours stable sur toutes les configurations ou presque). Sans surprise, les vitesses de prédiction des MoE sont particulièrement bonnes, et les vitesses de prédiction des denses sont nettement plus basses. Dans les deux, c'est tout à fait utilisable.

Pour référence, quand MTP est activé, Qwen 3.6 27B me donne plutôt environ 40 tokens/s. Autrement dit, très confortable.


## Le préremplissage

![Le préremplissage de contexte sur 5 GPU](https://i.imgur.com/W3dRgSg.png)

Clairement, c'est rapide.

Au début, on constate une augmentation de la vitesse avec la taille du contexte. Mais c'est très probablement juste des artéfacts : Je suppose que ces contextes sont trop petits pour mesurer correctement la vitesse sur un système si rapide 💪.

Ensuite, on a une petite surprise : on voit que la vitesse de préremplissage diminue de façon importante avec la taille du contexte. Mais même avec cette diminution importante, on reste à des vitesses tout à fait respectables.

En utilisation pratique, avec Qwen 3.5 27B et 35B, ça donne ça:

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   |                 |              |
|                       | MoE   |        | 2750            | 1s           |
|                       | Dense |        | 1000            | 2,5s         |
| Opencode              |       | 8000   |                 |              |
|                       | MoE   |        | 3650            | 2,5s         |
|                       | Dense |        | 1450            | 5,5s         |
| Open-WebUI outillé    |       | 20000  |                 |              |
|                       | MoE   |        | 3650            | 5,5s         |
|                       | Dense |        | 1500            | 13s          |
| PDF de 100 pages      |       | 45000  |                 |              |
|                       | MoE   |        | 3350            | 13,5s        |
|                       | Dense |        | 1350            | 33s          |
| Reprise de session    |       | 64000  |                 |              |
|                       | MoE   |        | 3150            | 20s          |
|                       | Dense |        | 1250            | 50s          |

## Conclusion subjective

Bref, c'est globalement confortable pour les modèles ≤35b. Qwen 122b est utilisable, mais en q2, et sans être confortable.


# CPU et RAM uniquement

On va tout de suite attaquer le cas le plus absurde. Là, clairement, on prend un éléphant, et on essaye de le faire rentrer dans un tutu taille S pour le faire danser.


## La prédiction

![La prédiction sur CPU uniquement](https://i.imgur.com/4wrR7Bc.png)

Sans surprise, avec de la DDR4, c'est lent. Même le modèle 4B est à peine utilisable.

Avec de la DDR5, le 4B et 9B seraient probablement utilisables, et, chose amusante, un modèle 122B MoE en q2 pourrait être utilisable aussi.

Tous les autres (≥27B et ≥q4) sont juste inutilisables. 

![Absurde, on vous dit !](https://i.imgur.com/waO1pmb.png)


## Le préremplissage

![Le préremplissage de contexte sur CPU uniquement](https://i.imgur.com/quftnNu.png)

Premier constat, c'est **beaucoup** plus lent qu'en GPU (et l'eau, ça mouille).

Deuxième constat, la vitesse descend aussi avec la taille du contexte. Sauf qu'on part de très bas dès le départ. Cette descente fait d'autant plus mal.

Vous noterez que je n'ai pas testé plus que des contextes de 32K. C'est parce que c'était horriblement long, et que j'ai une vie (sisi, j'vous jure).

En utilisation pratique, avec Qwen 3.5 4B, 27B et 35B A3B, ça donnerait ça :

|                       |           | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-----------|--------|-----------------|--------------|
| Home Assistant        |           | 2500   |                 |              |
|                       | MoE A3B   |        | 25,5            | **1m 40s**     |
|                       | Dense 4B  |        | 43              | **1m**         |
|                       | Dense 27B |        | 7               | **5m 20s**     |
| Opencode              |           | 8000   |                 |              |
|                       | MoE A3B   |        | 22              | **6m**         |
|                       | Dense 4B  |        | 34              | **4m**         |
|                       | Dense 27B |        | 6               | **20m 30s**   |
| Open-WebUI outillé    |           | 20000  |                 |              |
|                       | MoE A3B   |        | 17              | **20m**       |
|                       | Dense 4B  |        | 20              | **16m**       |
|                       | Dense     |        | 5               | **1h 10m**    |
| PDF de 100 pages      |           | 45000  |                 |              |
|                       | MoE A3B   |        | 16              | **45m**       |
|                       | Dense 4B  |        | 7               | **1h 40m**    |
|                       | Dense 27B |        | 3               | **4h**        |
| Reprise de session    |           | 64000  |                 |              |
|                       | MoE A3B   |        | 16              | **1h**        |
|                       | Dense 4B  |        | 6               | **3h**        |
|                       | Dense 27B |        | 3               | **6h 30m**    |

Et là, on se rend compte que même les petits modèles sont inutilisables.


## Conclusion objective

À moins d'avoir la patience d'un moine bouddhiste, il est évident que c'est juste inutilisable. Et sur ce coup-là, même la meilleure DDR5 ne va pas vous sauver.

Le seul cas d'utilisation que je pourrais imaginer serait dans des batchs. Et encore, il ne faut pas être trop pressé.


# Sur une Nvidia RTX 3060 12Go, avec débordement

Sur une carte RTX 3060 12Go, la plupart des bons modèles ne rentrent pas en VRAM. Mais on peut les faire déborder sur la RAM : J'ai demandé à `llama-bench` de mettre certaines couches du modèle sur la VRAM (`-ngl`), et le reste en RAM.

Et là, on commence à se rapprocher de ce qui est vendu sur les réseaux sociaux.


## La prédiction

![La prédiction sur GPU + débordement](https://i.imgur.com/RzOKMun.png)

Exclusivement en MoE 35B, on arrive sur quelque-chose d'utilisable, mais pas vraiment confortable.
Les denses et le 122B sont juste inutilisables.


## Le préremplissage

![La lecture de contexte sur GPU + débordement](https://i.imgur.com/9MEV5tS.png)

La vitesse chute aussi, mais nettement moins. En fait, elle est presque stable. Ce qui tombe bien, parce qu'elle commence assez bas.

En utilisation pratique, avec Qwen 3.5 27B et 35B, ça donne ça :

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   |                 |              |
|                       | MoE   |        | 270             | **9s**        |
|                       | Dense |        | 190             | **13s**       |
| Opencode              |       | 8000   |                 |              |
|                       | MoE   |        | 265             | 30s          |
|                       | Dense |        | 190             | 40s          |
| Open-WebUI outillé    |       | 20000  |                 |              |
|                       | MoE   |        | 255             | **1m 15s**    |
|                       | Dense |        | 180             | **1m 50s**    |
| PDF de 100 pages      |       | 45000  |                 |              |
|                       | MoE   |        | 245             | 3m           |
|                       | Dense |        | 165             | 4m 30s       |
| Reprise de session    |       | 64000  |                 |              |
|                       | MoE   |        | 240             | 4m 30s       |
|                       | Dense |        | 160             | 6m 30s       |

## Conclusion subjective

On arrive sur quelque chose d'utilisable **parfois**, mais vraiment pas confortable.

Avec de la DDR5, on peut espérer arriver sur des résultats plus sympas, utilisables, et nettement plus proches d'être confortables.


# Sur une Nvidia RTX 3060 12Go, avec débordement, avec `--cpu-moe`

`llama-server` a une option bien pratique : `--cpu-moe`. Comme son nom l'indique, cette option est réservée aux modèles MoE. Avec cette option, on ne charge en VRAM que la partie routeur, les couches d'attention, etc. Les experts, eux, restent en RAM. L'idée est que les experts tous ensemble sont la partie la plus gourmande en VRAM/RAM du modèle. Mais individuellement, ils sont chacun relativement petits, et le CPU peut potentiellement se charger d'eux. Bref, à première vue, un excellent compromis.

À noter qu'il y a aussi l'option `--n-cpu-moe X` qui permet de charger des couches supplémentaires en VRAM. Mais il faut optimiser ça à la main pour chaque modèle et chaque matériel. Autant dire que ça aurait été trop pénible à faire pour ce journal.


## La prédiction

![La prédiction sur GPU + --cpu-moe](https://i.imgur.com/Apx0q3y.png)

On est entre 2 et 3 fois plus rapide. En MoE, c'est enfin confortable à utiliser.

Autrement dit, le gain est net 🎉 ! Ayé, on y est ! On est sauvés ! La terre promise par les réseaux sociaux ! On va enfin pouvoir résilier notre abonnement Claude Opus, et bruler les datacenters des sociétés qui font du LLM cloud, avant qu'ils ne détruisent notre planète ! Et le tout sans investir plusieurs milliers d'euros dans du matériel !

Cerise sur le gâteau, le 122B a l'air utilisable 🎉 !


## Le préremplissage

Ah mais zut, il reste cette histoire de préremplissage. Bah, comme pour la prédiction, ×2~×3 aussi, tranquillou, non ?

Et ben non 😭.

![La lecture de contexte sur GPU + --cpu-moe](https://i.imgur.com/JtudG5o.png)

Le 35B est même un peu plus lent ! Et le 122B n'est en fait toujours pas utilisable 😭.

En utilisation pratique, avec Qwen 3.5 35B, ça donne ça:

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   | 216             | **11s**       |
| Opencode              |       | 8000   | 210             | 38s          |
| Open-WebUI outillé    |       | 20000  | 205             | **1m 30s**    |
| PDF de 100 pages      |       | 45000  | 200             | 3m 40s       |
| Reprise de session    |       | 64000  | 200             | 5m 10s       |

Comme on le voit, pour le préremplissage, on a sensiblement les mêmes résultats qu'en débordement simple … voire de moins bons résultats.


## Conclusion subjective

On est limité aux modèles MoE.

C'est nettement mieux en prédiction, mais le préremplissage fait qu'on reste fondamentalement coincé sur quelque-chose d'utilisable **parfois**, et pas vraiment confortable.

Avec de la DDR5, on peut espérer quelque chose d'utilisable en général, voire presque confortable.

Si vous avez assez de VRAM, vous pouvez aussi jouer avec `--n-cpu-moe` et `nvtop` pour optimiser ces résultats. Basé sur mon expérience personnelle, vous pouvez les améliorer sensiblement. Mais tant que vous avez une part non-négligeable des couches en RAM plutôt qu'en VRAM, vous n'arrivez pas à des résultats fondamentalement différents.


# Modèles plus gros que la RAM

Llama.cpp utilise par défaut la fonction `mmap()` pour charger les modèles en RAM. Le gros avantage de `mmap()`, c'est que ça laisse le noyau charger les données en mémoire (cache), ou pas, à la demande. En conséquence, on pourrait imaginer charger des MoE plus gros que notre RAM, et laisser le noyau swapper les morceaux de modèles entre notre NVMe et la RAM automatiquement, en fonction des besoins. En théorie, ça fonctionne. Mais en pratique, les performances sont tellement dégradées que c'est complètement inutilisable. C'est tellement dégradé que je ne vais pas m'embêter à sortir des chiffres (eh, mine de rien, c'est super long à faire ces fichus benchmarks ! 🫩).


# `mmap()` et `--no-mmap`

En fait, cette utilisation de `mmap()` est surtout pertinente si le modèle tient entièrement en VRAM. Elle permet de ne pas garder inutilement une copie complète du modèle en RAM. Si vous avez plus de VRAM que de RAM, elle permet aussi de quand même charger un modèle plus gros que votre RAM en VRAM.

Si vous faites du débordement sur le CPU+RAM, je vous recommande de désactiver l'utilisation de `mmap()` (`--no-mmap`). Dans ce cas, comme les logs de `llama-server` l'indiquent, les performances sont nettement meilleures sans `mmap()`.


# Sur une seule Nvidia RTX 3060 12Go, sans débordement, avec des petits modèles

Les petits modèles sont plus bêtes, mais selon votre utilisation, ils peuvent être suffisants.

À noter qu'aucun des petits modèles Qwen 3.5 n'est un MoE. De toute façon, je ne pense pas que cette architecture soit pertinente à ces tailles là.


## La prédiction

![La prédiction sur une carte, petits modèles](https://i.imgur.com/KHibaJp.png)

Sans surprise, plus le modèle est petit, plus ça va vite 🏎️.

Sur ce graph, la vitesse décroche après 64K : à ces tailles de contexte, mon script de benchmark a déclenché un débordement sur la RAM. Mon script est probablement assez pessimiste. Il y a peut-être moyen de faire rentrer plus de couches en VRAM pour éviter cette chute.

Chose amusante, si on active MTP, le modèle 2B devient nettement plus lent : 110 tokens/s au lieu de 160 tokens/s.


## Le préremplissage

![Le préremplissage sur une carte, petits modèles](https://i.imgur.com/BJ2t6Bo.png)

Pareillement, plus c'est petit, plus ça va vite. Ça va même ridiculement vite pour le 2B ⚡️⚡️⚡️.

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   |                 |              |
|                       | 2B    |        | 5915            | 0,5s         |
|                       | 4B    |        | 2570            | 1s           |
|                       | 9B    |        | 1690            | 1,5s         |
| Opencode              |       | 8000   |                 |              |
|                       | 2B    |        | 5750            | 1,5s         |
|                       | 4B    |        | 2480            | 3,2s         |
|                       | 9B    |        | 1650            | 5s           |
| Open-WebUI outillé    |       | 20000  |                 |              |
|                       | 2B    |        | 5340            | 3,7s         |
|                       | 4B    |        | 2280            | 9s           |
|                       | 9B    |        | 1550            | 13s          |
| PDF de 100 pages      |       | 45000  |                 |              |
|                       | 2B    |        | 4650            | 10s          |
|                       | 4B    |        | 1960            | 23s          |
|                       | 9B    |        | 1390            | 32s          |
| Reprise de session    |       | 64000  |                 |              |
|                       | 2B    |        | 4280            | 15s          |
|                       | 4B    |        | 1786            | 35s          |
|                       | 9B    |        | 1306            | 49s          |

Bref, pour vitesse de préremplissage, on est large.


## Intelligence

![Dah !](https://i.imgur.com/PZpc8NR.png)

Sans commentaire [🤦‍♂️🤦🤦‍♀️](https://www.youtube.com/watch?v=g-bVEc8oZvk).


## Conclusion objective

Si vous êtes prêt à échanger de l'intelligence contre de la vitesse, prendre un modèle plus petit 🤏🧠 est un compromis très efficace. Par contre, il ne faudra pas venir vous plaindre si votre LLM est teubé 📉.

Aussi, si vous décidez d'utiliser ces petits modèles, je vous recommande fortement d'utiliser les variantes q8. Les petits sont déjà assez bêtes de base, on va éviter de trop les lobotomiser en plus. En q8 au lieu de q4, vous pouvez grosso-modo diviser par 2 les vitesses indiquées ici.


# AMD RX 9070 XT 16Go

Cette carte graphique est intéressante car c'est une carte grand public récente, assez typique, moyen de gamme, un peu chère mais pas trop (environ 750€ au moment où j'écris ces lignes). Elle a une bande passante mémoire de 645 Go/s, soit presque deux fois plus que la Nvidia RTX 3060 12Go.

Dans le cas des cartes AMD, comme [on me l'avait mentionné sur mon précédent journal](https://linuxfr.org/users/jflesch/journaux/auto-heberger-ses-ia-materiel-et-optimisation-de-l-inference#comment-2026983), le backend Vulkan est effectivement plus rapide que le backend Rocm. Ces tests ont donc été faits avec le backend Vulkan.

La carte AMD utilisée ici n'a que 16 Go de VRAM, donc Qwen 3.5 27B et 35B q4 n'ont pu être testés qu'avec du débordement CPU+RAM. Pour aller droit au but, je ne présente ici que les résultats avec `--cpu-moe`.

Parce que je suis un pauvre entouré de pauvres, on reste sur de la RAM DDR4 à 3200 MHz partout.

Merci à Quarby de m'avoir autorisé à monopoliser sa machine pendant 2 jours pour ces benchmarks 😁.


## La prédiction

![Prédiction sur l'AMD](https://i.imgur.com/J1cKmmP.png)

Elle est matériellement nettement plus rapide que la Nvidia, pourtant la vitesse de prédiction est un peu en dessous de la Nvidia RTX 3060 12Go. C'est en fait plus ou moins normal : L'utilisation de `--cpu-moe` fait que le goulot d'étranglement devient le CPU et la RAM plus que le GPU. Je n'ai malheureusement pas pu monitorer la carte pendant le benchmark, mais je suis prêt à parier qu'elle se tournait les pouces. Du coup, à RAM identique, avoir des performances similaires n'est pas une surprise. Le fait qu'on soit un peu en dessous de la Nvidia vient possiblement d'une moins bonne optimisation de la stack logicielle.


## Le préremplissage

![Préremplissage sur l'AMD](https://i.imgur.com/l6086Xf.png)

Là, elle est un poil plus rapide que la Nvidia RTX 3060.

En utilisation pratique, avec Qwen 3.5 35B, ça donne ça:

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   | 270             | **9s**        |
| Opencode              |       | 8000   | 265             | 30s          |
| Open-WebUI outillé    |       | 20000  | 255             | **1m 20s**    |
| PDF de 100 pages      |       | 45000  | 245             | 3m 5s        |
| Reprise de session    |       | 64000  | 235             | 4m 30s       |


## Conclusion subjective

Comme mentionné précédemment, la façon dont j'ai benchmarké rendait très difficile l'utilisation de `--n-cpu-moe` au lieu de juste `--cpu-moe`, et je ne l'ai donc pas fait. Ici, cette carte ayant plus de VRAM que la Nvidia, il faudrait jouer avec `--n-cpu-moe` pour charger plus de couches en VRAM. En jouant sur ce paramètre, il est probablement possible d'obtenir des résultats un peu meilleurs que sur la Nvidia RTX 3060 12Go. Ceci dit, d'expérience avec cette option, il ne faut pas non plus espérer des résultats extraordinairement meilleurs. Tant qu'il y a débordement, le goulot d'étranglement restera le CPU et la RAM.


# Intel Arc Pro B60

La Intel B60 (ainsi que sa grande sœur la B70) est une carte récente, avec un ratio prix/VRAM imbattable (750€ pour 24Go), mais qui est plus lente que ces concurrentes AMD ou Nvidia.

Cette carte affiche une bande passante mémoire de 450 Go/s, soit plus qu'une Nvidia RTX 3060 (360 Go/s), mais nettement moins que l'AMD RX 9070 XT. Avec ses 24Go de VRAM, les modèles Qwen 3.5 27B et 35B en q4 rentrent intégralement dessus. On pourrait donc s'attendre à des performances tout à fait honorables.

Basé sur mon expérience, si vous optez pour cette carte, il faut impérativement savoir qu'elle a une spécificité : Les cartes Intel utilisent une mémoire virtuelle unifiée (*Unified Shared Memory*). Autrement dit, les données sur la RAM et la VRAM sont swappés automatiquement et de façon transparente. Donc vous pouvez préciser à llama-server les options `-ngl 999 -fit off`, et il vous dira que tout est rentré en VRAM, mais en fait, ça déborde. Ce débordement va se ressentir tout autant sur les performances que du débordement CPU+RAM llama.cpp classique. Ça peut même être pire.

Le backend utilisé ici est Sycl. J'ai testé brièvement le backend Vulkan avec cette carte, et les performances étaient 2 à 3 fois plus mauvaises.

On est toujours sur de la DDR4 3200 MHz.

## La prédiction

![Prédiction sur la B60](https://i.imgur.com/oz8QOzQ.png)

La vitesse de prédiction sur la B60 n'est pas dingue. Utilisable, mais pas super.

À noter que MTP peut améliorer cette vitesse (environ 20 tokens/s pour Qwen 3.6 27B q4).

Avec l'option `--cpu-moe`, elle est un peu plus lente que la AMD testée précédemment (un peu moins de 25 tokens/s VS un peu plus de 25 tokens/s). Mais comme elle peut faire rentrer les modèles entièrement dans sa VRAM, elle prend l'avantage.


## Le préremplissage

![Préremplissage sur la B60](https://i.imgur.com/2fmQnwX.png)

Meh. La B60 commence pas trop mal, mais les performances tombent avec la taille du contexte.


En pratique, ça donne ça :

|                       |       | Tokens | Vitesse moyenne | Temps estimé |
|-----------------------|-------|--------|-----------------|--------------|
| Home Assistant        |       | 2500   |                 |              |
|                       | MoE   |        | 820             | 3s           |
|                       | Dense |        | 450             | **5,6s**      |
| Opencode              |       | 8000   |                 |              |
|                       | MoE   |        | 740             | 11s          |
|                       | Dense |        | 380             | 21s          |
| Open-WebUI outillé    |       | 20000  |                 |              |
|                       | MoE   |        | 550             | 35s          |
|                       | Dense |        | 280             | **71s**       |
| PDF de 100 pages      |       | 45000  |                 |              |
|                       | MoE   |        | 400             | 1m 50s       |
|                       | Dense |        | 200             | 3m 45s       |
| Reprise de session    |       | 64000  |                 |              |
|                       | MoE   |        | 360             | 3m           |
|                       | Dense |        | 180             | 6m           |

Pour info, quand elle est testée avec l'option `--cpu-moe`, ces performances restent similaires à celle de la carte AMD testée précédemment.


## Conclusion subjective

Vu qu'on ne déborde pas, sans surprise, on gagne plusieurs avantages :

- Les performances sont nettement meilleures qu'avec une Nvidia RTX 3060 12Go avec débordement.
- Il est appréciable de ne pas être limité qu'aux MoE.
- On n'est pas dépendant de la vitesse de la RAM. Couplée à cette carte, une pomme de terre mal cuite avec de la DDR3 peut suffire. 
- Les pilotes Intel et une grande partie de la stack sont libres. Il manque toutefois le firmware de la carte et des bouts de l'API oneAPI.

Mais il faut admettre, ce n'est pas non plus extraordinaire. On reste entre utilisable et confortable.

J'ai le sentiment qu'on pourrait attendre plus de ce matériel. Du coup, plusieurs questions se posent :

- Est-ce que le backend logiciel Sycl pourrait être mieux optimisé ?
- Est-ce que la B70, plus performante, fait significativement mieux ?


# Conclusion globale

Il faut avoir à l'esprit que la vitesse de préremplissage chute avec la taille du contexte. Cette chute dépend entièrement de votre configuration matériel.

Le débordement CPU+RAM est utilisable … pour certaines utilisations spécifiques et/ou sur certains matériels spécifiques (💸…DDR5…💸). À coté de ça, les MoE peuvent effectivement être une option intéressante pour être plus confortable. Dans tous les cas, la vitesse de préremplissage ne peut pas être ignorée. En l'omettant, énormément de publications vous vendent du rêve et vous induisent potentiellement en erreur.

On remarque aussi qu'un assistant Home Assistant nécessite de la réactivité, et cela en fait un des problèmes les plus difficiles à résoudre avec un LLM auto-hébergé.


# Hors-sujet : mmproj en RAM

Une optimisation oubliée dans le précédent journal : si, comme moi, vous soumettez rarement des images à votre IA, vous pouvez garder le mmproj en RAM plutôt qu'en VRAM avec l'option `--no-mmproj-offload`.


# Hors-sujet : Quantification chez openrouter.ai

Chose intéressante :

J'avais vu passer des rumeurs disant que les modèles sur openrouter.ai [seraient](https://www.lesswrong.com/posts/KsyoSAyBRXtwzSugg/not-pinning-your-openrouter-provider-might-invalidate-your) [souvent](https://www.reddit.com/r/LocalLLaMA/comments/1udmltk/openrouter_model_prices_implying_heavier/) [quantifiés](https://news.ycombinator.com/item?id=45842152), sans que ce soit clairement indiqué.

À côté de ça, quand j'ai écrit cet article, ma machine IA était généralement monopolisée par les benchmarks. J'ai donc utilisé temporairement openrouter.ai + Qwen 3.6 27B. Et à ma surprise, je me suis retrouvé plusieurs fois avec des boucles infinies (*doom loops*). De mémoire, il me semble avoir surtout eu ce problème en auto-hébergeant ce modèle en q4, mais que très rarement en q8.

Curieux, non ? 🧐


# Hors-sujet : Versions anglaises

Si besoin, vous pouvez trouver mes journaux en versions anglaises ici :

- [Self-hosting your AIs : Generalities](https://jerome.flesch.info/blog/posts/20260515-selfhosting-llm/)
- [Self-hosting your AIs : Hardware and Inference Optimization](https://jerome.flesch.info/blog/posts/20260702-selfhosting-llm-hardware-and-inference-optimization/)
- [Self-hosting your LLMs (AIs) : CPU+RAM overflow and Mixture-of-Experts](https://jerome.flesch.info/blog/posts/20260803-selfhosting-llm-offloading-moe-and-benchmarks/)

