Trois runtimes, trois intentions

Ces trois projets sont régulièrement comparés comme s’ils visaient le même but. Ils ne le font pas, et c’est précisément ce qui rend leurs forces et leurs angles morts respectifs prévisibles, à condition de partir de l’intention d’origine. vLLM est né en 2023 dans un labo de Berkeley pour maximiser le débit d’un service multi-utilisateurs. llama.cpp est né en 2023 aussi, mais pour faire tourner Llama sur un MacBook, sans dépendances et avec un binaire compilé en place. TensorRT-LLM est l’outil de NVIDIA, conçu pour extraire le dernier pourcent de performance de son propre matériel.

Choisir, c’est d’abord identifier laquelle de ces trois intentions est la vôtre, et accepter que les compromis qui en découlent ne sont pas négociables.

vLLM : le débit serveur

vLLM a rendu populaires deux idées aujourd’hui standard, et qu’il vaut la peine de comprendre dans le détail, parce qu’elles expliquent la totalité de son avantage en débit. La première est PagedAttention Algorithme introduit par vLLM qui gère le KV cache comme la mémoire virtuelle d'un système d'exploitation : par pages, sans exiger un bloc contigu par requête. Élimine la fragmentation interne et externe, permet de servir 2 à 4× plus de requêtes concurrentes sur la même VRAM. Approfondir dans le glossaire , que vLLM a introduite. Le KV cache Mémoire des vecteurs clé et valeur déjà calculés pour chaque token traité par un LLM. Évite de recalculer l'attention sur tout l'historique, au prix d'une consommation mémoire qui croît avec le contexte. Approfondir dans le glossaire , la mémoire des K et V de chaque token déjà traité, est gourmand et croît à chaque token généré. L’approche naïve consistait à réserver pour chaque requête un bloc contigu en VRAM, dimensionné sur la longueur de contexte maximale annoncée. Une requête courte laissait son bloc presque vide ; deux requêtes longues se disputaient des trous trop petits. Mesuré sur des charges réelles, l’occupation utile du KV cache plafonnait autour de 20–40 %. PagedAttention transpose la mémoire virtuelle paginée d’un OS : le cache est découpé en blocs de taille fixe (typiquement 16 tokens), attribués à la demande, sans aucune exigence de contiguïté. La fragmentation interne tombe à un demi-bloc en moyenne ; l’externe disparaît. L’occupation utile remonte à ~96 % et le même GPU sert deux à quatre fois plus de requêtes concurrentes à VRAM constante.

La seconde idée est le batching continu Ordonnancement à l'itération : ajouter et retirer des requêtes du batch à chaque pas de génération, au lieu d'attendre qu'un batch entier se termine. Formalisé par Orca (OSDI 2022), popularisé par vLLM. Multiplie par 2 à 4 le débit d'un serveur d'inférence sous forte concurrence. Approfondir dans le glossaire , l’ordonnancement à l’itération, formalisé auparavant par Orca (OSDI 2022). Le batching classique attendait qu’un lot de N requêtes se termine pour lancer le suivant : la requête la plus lente du lot dictait la latence de toutes les autres, et toute nouvelle requête patientait jusqu’à la fin du lot en cours. Le batching continu retourne le problème : à chaque pas de génération, le scheduler regarde l’état de chaque slot, retire ceux qui ont émis leur token de fin, et y branche immédiatement une nouvelle requête en attente. Le GPU ne désempile jamais. Combiné à PagedAttention, qui rend l’allocation mémoire d’une nouvelle requête triviale, ce mécanisme transforme un serveur LLM en pipeline d’inférence permanent. vLLM ne l’a pas inventé (Orca l’a publié un an plus tôt) mais l’a porté à l’échelle, en open source, sur les GPU que tout le monde utilise.

Le revers de cette spécialisation : vLLM reste calibré pour le GPU datacenter. Un écosystème de plugins gère désormais TPU, Gaudi, Ascend, Apple Silicon, mais la cible historique et le sweet spot d’optimisation restent les GPU haut de gamme. Sur matériel modeste, hétérogène ou simplement absent, ce n’est pas son terrain.

llama.cpp : le local et le portable

llama.cpp prend le problème par l’autre bout. Pas de runtime lourd, pas de dépendance Python obligatoire : un binaire C++ qui charge un fichier GGUF et tourne sur à peu près tout : CPU x86 et ARM, Apple Silicon, GPU NVIDIA via CUDA, AMD via HIP/ROCm, Intel via SYCL, Apple via Metal, ou cross-plateforme via Vulkan, et même en hybride CPU/GPU quand le modèle dépasse la VRAM disponible.

C’est le runtime du poste de travail, du prototype, de l’edge et de tout déploiement qui doit rester simple à empaqueter. Sa quantification GGUF GPT-Generated Unified Format. Format de fichier de llama.cpp qui stocke dans un seul fichier les tenseurs, leurs types de quantification, le vocabulaire et les métadonnées du modèle. Sa structure alignée permet de le lire par mmap : le modèle « démarre » en une fraction de seconde. Approfondir dans le glossaire très fine fait tenir des modèles étonnamment gros sur du matériel grand public, comme un 13B sur un MacBook Air ou un 70B en Q4 sur une station de travail à 64 Go de RAM.

Son angle mort : la concurrence. llama.cpp excelle sur une à quelques requêtes ; il n’a pas d’ordonnanceur pensé pour entrelacer des dizaines de générations simultanées. Une fois passé ce seuil, chaque nouvelle requête allonge la latence des précédentes au lieu de partager le coût de lecture des poids.

TensorRT-LLM : la performance verrouillée NVIDIA

TensorRT-LLM compile votre modèle en un engine binaire optimisé pour une architecture GPU précise : fusion de kernels (plusieurs opérations enchaînées en un seul lancement, ce qui élimine les allers-retours en mémoire), sélection des noyaux les plus rapides parmi plusieurs implémentations candidates, exploitation des formats FP8/FP4 câblés dans les Tensor Cores Unités matérielles spécialisées dans les multiplications de matrices à basse précision, introduites par NVIDIA avec Volta (2017). Chaque génération ajoute des formats supportés : FP16 → FP8 (Hopper) → FP6/FP4 (Blackwell). Ce sont elles qui exécutent l'essentiel du calcul d'inférence. Approfondir dans le glossaire de Hopper et Blackwell. Sur le matériel visé, c’est presque toujours le plus rapide des trois, en débit comme en latence, avec une marge typique de quelques pourcents à 20-30 % sur les charges où la fusion de kernels paie le plus.

Le prix à payer est réel et structurel. L’engine compilé est lié à la version exacte du GPU, du driver CUDA et de la version de TensorRT-LLM utilisée à la compilation. Un upgrade matériel ou logiciel implique de rebâtir tous les engines. Le cycle de build lui-même est lourd, de l’ordre de la dizaine de minutes à plusieurs heures selon le modèle, et l’ensemble vous arrime fermement à l’écosystème NVIDIA, sans porte de sortie. C’est un excellent choix quand le matériel est figé pour les 12-24 prochains mois et que chaque pourcent compte ; un mauvais choix quand le parc évolue ou qu’on veut garder la possibilité de basculer chez un autre fournisseur.

Comparatif : débit, latence, ergonomie

Comparatif de débit entre vLLM, llama.cpp et TensorRT-LLM (Tokens/s, Llama 3 8B, GPU unique, contexte 2k)
Requête uniqueSous concurrence
vLLM 951,85k
llama.cpp 110240
TensorRT-LLM 1302,10k

Profils indicatifs sur un même GPU. vLLM et TensorRT-LLM mesurés sous concurrence ; llama.cpp en requête unique.

La leçon du graphe : en requête unique, les trois runtimes sont proches : l’avantage architectural des serveurs ne se voit pas, parce qu’il n’y a rien à batcher. C’est sous concurrence que vLLM et TensorRT-LLM décollent, parce que c’est exactement le scénario pour lequel ils ont été conçus. Un chiffre de tokens/s sans précision sur la concurrence ne dit rien d’exploitable : à concurrence 1, le batching continu et PagedAttention dorment ; à concurrence 64, ils représentent la quasi-totalité de l’écart mesuré.

CritèrevLLMllama.cppTensorRT-LLM
CibleServeur multi-requêtesLocal / edge / protoProduction NVIDIA figée
MatérielGPU datacenterCPU, Apple, GPU variéGPU NVIDIA spécifique
Mise en routeRapideTrès rapideLente (build engine)
Débit concurrentExcellentFaibleExcellent
PortabilitéMoyenneExcellenteFaible
Tableau 1 : Matrice de décision synthétique.

Comment choisir

Trois questions tranchent l’essentiel des décisions. Combien de requêtes simultanées au pic ? En dessous d’une poignée, le batching continu n’a personne à orchestrer et tout runtime convient ; au-delà, vLLM ou TensorRT-LLM deviennent obligatoires sous peine de payer la concurrence en latence linéaire. Le matériel est-il figé et exclusivement NVIDIA pour les 12-24 prochains mois ? Si oui, TensorRT-LLM mérite son cycle de build : c’est la seule manière d’extraire les derniers 20–30 % de débit. Si le parc évolue, le verrouillage devient une dette. Faut-il que ça tourne partout, simplement, sans coordination d’infrastructure ? Alors llama.cpp, qui se compile en cinq minutes et lit un GGUF sur toute machine vaguement récente.

Beaucoup d’équipes finissent avec deux runtimes : llama.cpp pour le développement local et l’edge, vLLM pour le service en production, chacun appliqué là où son intention d’origine paie.

Conclusion

Il n’y a pas de « meilleur runtime » dans l’absolu : il y a un runtime adapté à un scénario : débit serveur, portabilité, ou performance maximale verrouillée. La question intéressante n’est donc pas lequel utiliser, mais : votre contrainte dominante va-t-elle changer dans les douze prochains mois (pic de concurrence à venir, migration matérielle, ouverture multi-fournisseurs) ? Si oui, vous choisissez peut-être moins un runtime qu’un futur portage. Pour les déploiements contraints, la suite logique est Jetson Orin et edge AI.

Sources et méthode

Cet article s’appuie sur la documentation et les dépôts officiels des trois projets, et sur les articles de recherche fondateurs.

Méthode : les profils de débit du graphe sont indicatifs : ils n’ont pas été mesurés sur un banc publié ici et dépendent fortement du modèle, du GPU, de la quantification et de la configuration. Ils illustrent un ordre de grandeur et une dynamique relative (les trois runtimes proches en requête unique, vLLM et TensorRT-LLM qui décollent sous concurrence), pas un classement absolu. Toute décision de production doit reposer sur un benchmark sur le matériel cible.