Je me souviens de la première fois où j’ai dû déployer un grand modèle de langage pour une application à fort trafic. Naïvement, j’avais lancé l’inférence directement sur PyTorch. Les résultats ont été immédiats : des temps de réponse corrects pour un utilisateur unique, mais un effondrement total dès que plusieurs requêtes arrivaient en même temps. C’est ce qui m’a poussé à me plonger dans TensorRT-LLM, une bibliothèque open-source développée par NVIDIA.
Conçue spécifiquement pour accélérer l’inférence des LLM sur les processeurs graphiques de la marque, elle promet des performances de niveau industriel, allant souvent jusqu’à quadrupler le débit par rapport à une exécution PyTorch native. Cet outil y parvient en combinant une gestion avancée de la mémoire, des techniques de quantification poussées et des optimisations de kernels propres au matériel.
Ce qu’il faut retenir avant de commencer
- Performances maximales : TensorRT-LLM offre le débit le plus élevé possible sur le matériel NVIDIA, mais cela demande une étape de compilation dédiée.
- Complexité d’installation : Contrairement à des alternatives plus directes comme vLLM, la mise en place initiale est exigeante. Elle nécessite souvent de passer par des conteneurs Docker pour éviter les conflits de dépendances.
- Le bon compromis : Dans la pratique, on adopte souvent une approche hybride : vLLM pour le prototypage rapide et l’expérimentation, et TensorRT-LLM pour la production à grande échelle où chaque milliseconde et chaque centime d’hébergement comptent.
Les piliers technologiques de TensorRT-LLM
Pour optimiser les réseaux de neurones et générer des moteurs binaires ultra-rapides, la bibliothèque s’appuie sur quatre techniques majeures :
- Le batching dynamique (In-Flight Batching) : Au lieu d’attendre que l’ensemble d’un groupe de requêtes soit traité avant d’en accepter de nouvelles, cette méthode traite les requêtes au fur et à mesure de leur arrivée, évitant ainsi de laisser le GPU inactif.
- Le cache KV paginé (Paged KV Caching) : En s’inspirant du concept de mémoire virtuelle des systèmes d’exploitation, cette technique alloue la mémoire des clés et valeurs (Key-Value) bloc par bloc. Cela réduit drastiquement la fragmentation de la mémoire GPU.
- La quantification avancée : Elle permet de compresser les modèles en utilisant des formats à faible précision (FP8, NVFP4, INT8, INT4, AWQ) pour maximiser le débit tout en limitant la perte de précision mathématique.
- La fusion de kernels (Kernel Fusion) : Cette approche regroupe plusieurs opérations successives (comme LayerNorm, les multiplications de matrices et les fonctions d’activation) en un seul et unique kernel CUDA. On évite ainsi les allers-retours coûteux dans la mémoire globale du GPU.
Du côté de l’architecture, la bibliothèque est construite autour de PyTorch. Elle propose une API Python de haut niveau pour faciliter le développement, tout en conservant les performances d’un runtime C++ de bas niveau pour l’exécution. Elle gère nativement le parallélisme multi-GPU et multi-nœuds (Tensor Parallelism et Pipeline Parallelism) via les primitives NCCL d’NVIDIA, ce qui s’avère indispensable pour faire tourner des modèles massifs comme DeepSeek-R1 ou Llama 3/4.
De plus, l’exécution de type “Define-by-Run” permet de valider et de déboguer rapidement les modèles en Python avant de lancer la compilation finale. Enfin, tout est pensé pour s’intégrer directement avec Triton Inference Server grâce à un backend C++ dédié.
Comment installer TensorRT-LLM sans perdre patience ?
Je préfère être honnête : tenter d’aligner manuellement les versions de CUDA, des pilotes graphiques et des dépendances C++ sur une machine physique peut rapidement devenir un cauchemar. C’est pourquoi je recommande vivement de passer par les conteneurs Docker pré-construits disponibles sur le catalogue NVIDIA NGC.
Voici les trois options de déploiement qui s’offrent à vous.
Option 1 : Utiliser le conteneur Docker (Recommandé)
Cette méthode regroupe automatiquement les bonnes versions de CUDA, TensorRT, PyTorch et MPI. On commence par récupérer l’image officielle :
docker pull nvcr.io/nvidia/tensorrt-llm/release:latest
Puis on lance le conteneur en veillant à partager l’intégralité des GPU et de la mémoire partagée :
docker run --rm -it --gpus all --ipc=host \
-v $(pwd):/workspace \
-v ~/.cache/huggingface:/root/.cache/huggingface \
nvcr.io/nvidia/tensorrt-llm/release:latest
Option 2 : Installation native sur Linux (via pip)
Si vous devez impérativement travailler directement sur votre système Ubuntu (bare-metal), veillez d’abord à installer les dépendances système requises :
sudo apt-get update && sudo apt-get -y install libopenmpi-dev libzmq3-dev
Créez ensuite un environnement virtuel Python propre et installez le paquet :
python3 -m venv trtllm_env
source trtllm_env/bin/activate
pip install --upgrade pip setuptools wheel
pip install tensorrt-llm --extra-index-url https://pypi.nvidia.com
Option 3 : Installation sur Windows (GeForce RTX Série 40)
TensorRT-LLM prend en charge Windows en natif pour les configurations dotées d’un seul GPU. Assurez-vous d’avoir installé le toolkit CUDA, Git et Python 3.10+. Lancez ensuite l’installation dans votre terminal PowerShell :
pip install tensorrt_llm --extra-index-url https://pypi.nvidia.com --extra-index-url https://download.pytorch.org/whl/cu121
Pour vérifier que tout fonctionne correctement, vous pouvez exécuter cette commande rapide dans votre terminal :
python3 -c "import tensorrt_llm; print(tensorrt_llm.__version__)"
Maîtriser la quantification des modèles
La quantification est le levier principal pour réduire l’empreinte mémoire d’un modèle et accélérer l’inférence. En convertissant les poids d’un modèle FP16 ou BF16 vers des formats de moindre précision, on peut diviser sa taille par quatre. Le tout est géré via un outil unifié appelé NVIDIA TensorRT Model Optimizer (ModelOpt), qui prend en charge la quantification post-entraînement (PTQ) ou l’entraînement conscient de la quantification (QAT) pour générer des fichiers optimisés au format .safetensors.
Voici un récapitulatif pour vous aider à choisir la bonne stratégie en fonction de votre matériel :
| Méthode | Avantage principal | Cas d’usage recommandé | Matériel requis minimum |
|---|---|---|---|
| FP8 (Per-Tensor / Block) | Débit maximal, perte de précision quasi nulle. | Serveurs de production (Batch Size ≥ 16). | Hopper (H100/H200), Blackwell. |
| NVFP4 (FP4) | Densité de calcul maximale. | Échelle extrême, très faible empreinte mémoire. | Architecture Blackwell (B100/B200). |
| INT4 AWQ / GPTQ | Réduction massive de la taille des poids. | Petits lots ou terminaux locaux (Batch Size ≤ 4). | Ampere (A100), Ada Lovelace (RTX série 40). |
| INT8 SmoothQuant | Bonnes performances de calcul sur cartes anciennes. | Production sur serveurs d’ancienne génération. | Ampere (A100), Turing (T4). |
| FP8 / NVFP4 KV Cache | Réduction de la taille du contexte en mémoire. | Contextes longs ou conversations multi-tours. | Hopper, Blackwell. |
Le processus de quantification se déroule en deux étapes claires : d’abord, exécuter le script quantize.py pour générer les métadonnées de configuration, puis appeler trtllm-build pour compiler le moteur.
Voici un exemple pour quantifier un modèle Llama en FP8 avec un cache KV également en FP8 :
python /app/tensorrt_llm/examples/quantization/quantize.py \
--model_dir ./Llama-3-8B-Instruct \
--dtype bfloat16 \
--qformat fp8 \
--kv_cache_dtype fp8 \
--calib_size 512 \
--output_dir ./Llama-3-8B-FP8-Checkpoint
Si vous préférez une approche de type “poids uniquement” avec de l’INT4 AWQ, utilisez plutôt cette commande :
python /app/tensorrt_llm/examples/quantization/quantize.py \
--model_dir ./Llama-3-8B-Instruct \
--dtype bfloat16 \
--qformat w4a16_awq \
--awq_block_size 128 \
--output_dir ./Llama-3-8B-AWQ-Checkpoint
Une fois votre point de contrôle quantifié obtenu, il ne vous reste plus qu’à compiler le moteur physique pour votre GPU :
trtllm-build \
--checkpoint_dir ./Llama-3-8B-FP8-Checkpoint \
--output_dir ./engines/Llama-3-8B-FP8-Engine \
--gemm_plugin float16 \
--max_batch_size 64
Pour gagner du temps en production, sachez que vous pouvez tout à fait dissocier la précision des poids et celle du cache KV (par exemple, des poids en w4a8_awq avec un cache KV en fp8). Une autre astuce consiste à utiliser des configurations pré-quantifiées prêtes à l’emploi, comme le modèle Llama-3.1-8B-Instruct-FP8 d’NVIDIA disponible directement sur Hugging Face.
Modèles pris en charge et compilation
La bibliothèque prend en charge un catalogue très large et régulièrement mis à jour. Attention toutefois : pour que la compilation fonctionne, l’architecture du modèle cible doit correspondre à une structure supportée par le code source.
Voici les principales catégories de modèles nativement compatibles :
- Modèles de langage autorégressifs : Meta (Llama 2, 3, 3.1, 4), Alibaba (Qwen, Qwen1.5, Qwen2, Qwen3), Google (Gemma, Gemma 2, Gemma 3, RecurrentGemma), Mistral AI (Mistral 7B, Mixtral 8x7B / 8x22B, Mistral NeMo), Microsoft (Phi-2, Phi-3, Phi-4), DeepSeek (DeepSeek-V3, DeepSeek-R1 avec optimisation multi-nœuds), IBM (Granite-3.0), DBRX, Falcon, Grok-1, InternLM2 et Baichuan2.
- Modèles multimodaux et de vision (VLM) : LLaVA (1.5, NeXT, OneVision), Qwen-VL (Qwen2-VL, Qwen3-VL), l’écosystème NVIDIA (VILA, NeVA, Video NeVA), MLLaMA (Llama 3.2 VLM), CogVLM, Fuyu, Kosmos et Phi-3-vision.
- Modèles de génération d’images et de vidéos : Les architectures de type Diffusion et Transformers comme FLUX ou Wan2, qui exploitent une pile d’inférence dédiée pour optimiser les boucles de débruitage et la mise en cache des étapes (TeaCache/Cache-DiT).
Si vous souhaitez sauter l’étape de compilation manuelle, vous pouvez utiliser les projets Optimum-NVIDIA de Hugging Face ou vous tourner vers les NVIDIA NIMs (NVIDIA Inference Microservices), qui sont des conteneurs de production prêts à l’emploi.
Pour compiler vous-même les poids d’un modèle au format standard (comme des fichiers safetensors), la méthode classique se déroule ainsi :
# 1. Conversion des poids vers le format intermédiaire de TensorRT-LLM
python /app/tensorrt_llm/examples/llama/convert_checkpoint.py \
--model_dir ./Meta-Llama-3-8B-Instruct \
--output_dir ./llama-3-8b-ckpt \
--dtype bfloat16
# 2. Compilation du moteur physique
trtllm-build \
--checkpoint_dir ./llama-3-8b-ckpt \
--output_dir ./engines/llama-3-8b-engine
TensorRT-LLM vs vLLM : Comment choisir ?
Ces deux frameworks dominent le marché de l’inférence haute performance, mais ils répondent à des philosophies de conception radicalement différentes.
| Critère | vLLM | TensorRT-LLM (NVIDIA) |
|---|---|---|
| Philosophie | Simplicité d’utilisation, approche orientée service. | Performance brute, optimisation matérielle maximale. |
| Étape de chargement | Aucune compilation requise ; chargement direct depuis Hugging Face. | Nécessite de compiler les poids en moteurs statiques .engine. |
| Compatibilité matérielle | Multi-plateforme (NVIDIA, AMD, Intel, TPU). | Strictement limité aux GPU NVIDIA. |
| Débit relatif | Modéré à élevé (80% à 90% des performances de TRT-LLM). | Le plus élevé possible (10 à 30% plus rapide). |
| Time to First Token (TTFT) | Rapide et stable face aux variations de charge. | Le plus bas possible sur des configurations figées. |
| Sorties structurées (JSON) | Intégré nativement (via Outlines ou XGrammar). | Nécessite des implémentations personnalisées complexes. |
| Public cible | Prototypage rapide et utilisation locale. | Déploiements industriels à grande échelle. |
Le principal compromis réside dans le rapport entre la flexibilité de développement et l’optimisation des coûts d’infrastructure. Avec vLLM, une seule commande suffit pour lancer un point de terminaison compatible avec l’API OpenAI. Avec TensorRT-LLM, vous devez définir à l’avance des paramètres stricts (taille maximale de batch, longueur maximale d’entrée). Si une requête utilisateur dépasse ces limites définies lors de la compilation, l’exécution échoue tout simplement.
La stratégie de l’architecture hybride
Pour gérer à la fois un modèle de production ultra-stable et des cycles rapides d’évaluation de nouveaux modèles expérimentaux, l’industrie s’accorde sur un modèle d’architecture mixte. On évite de forcer ces deux types de charge sur un seul moteur.
On met alors en place une passerelle de routage de trafic (un API Gateway ou un orchestrateur comme Triton Server ou Ray Serve) :
- La ligne de production stable (TensorRT-LLM) : Le modèle de production figé est hébergé sur une instance dédiée TensorRT-LLM. Comme l’architecture ne change pas, l’effort de compilation initial est rentabilisé par une utilisation maximale des ressources matérielles et un coût d’infrastructure réduit sous forte charge.
- Le bac à sable expérimental (vLLM) : Les requêtes de test et d’évaluation sont envoyées vers une instance vLLM. Les chercheurs peuvent ainsi charger un nouveau modèle Hugging Face en deux minutes sans subir l’attente d’une compilation de 30 minutes.
Lorsque le nouveau modèle testé sur l’instance vLLM surpasse le modèle de production actuel sur vos indicateurs clés, il entre en phase de “diplômation”. On fige sa configuration, on le compile via quantize.py et trtllm-build, puis on le déploie sur la pile TensorRT-LLM pour remplacer l’ancien modèle.
Quelle différence avec TensorRT classique ?
C’est une question récurrente. Pour faire simple, TensorRT est un framework d’optimisation de bas niveau à but généraliste, capable de traiter tous types de réseaux de neurones (CNN, RNN, Transformers génériques, modèles de détection d’objets comme YOLO).
TensorRT-LLM est une surcouche de haut niveau écrite en Python et C++, spécialisée uniquement pour les grands modèles de langage autorégressifs. Elle utilise d’ailleurs TensorRT sous le capot.
La différence fondamentale réside dans la gestion de la nature dynamique des LLM. Un compilateur TensorRT classique gère des graphes statiques : une image de taille fixe entre, un vecteur de prédiction en sort. Un LLM, en revanche, fonctionne en deux phases distinctes : la phase de contexte (traitement de l’invite) et la phase de génération (génération de jetons un par un dans une boucle). Comme la longueur de la séquence change à chaque étape, TensorRT classique ne peut pas gérer efficacement cette boucle de manière native. TensorRT-LLM résout cela en découpant le modèle en blocs réutilisables optimisés en kernels CUDA, tout en y greffant le cache KV paginé et le batching dynamique.
Pour consulter le code source ou suivre les évolutions de cet outil, le dépôt officiel est accessible à cette adresse : https://github.com/NVIDIA/TensorRT-LLM.
TensorRT-LLM vs DeepSpeed : Deux mondes différents
Il ne faut pas confondre ces deux outils, car ils interviennent à des étapes opposées du cycle de vie des modèles. DeepSpeed, développé par Microsoft, est avant tout un framework conçu pour l’entraînement distribué et le fine-tuning à grande échelle, notamment grâce à ses techniques d’optimisation de mémoire ZeRO.
De son côté, TensorRT-LLM se concentre exclusivement sur l’inférence. Bien que DeepSpeed intègre des modules d’inférence (comme DeepSpeed FastGen et sa technique Dynamic SplitFuse, très efficace pour mélanger de longues requêtes d’entrée avec des étapes de génération courtes), TensorRT-LLM reste le choix privilégié pour maximiser le débit global d’un service en production sur architecture NVIDIA.
En résumé : utilisez DeepSpeed si vous devez entraîner un modèle à partir de zéro, effectuer du fine-tuning (LoRA/PEFT) ou travailler sur du matériel non-NVIDIA (comme des puces AMD). Tournez-vous vers TensorRT-LLM lorsque vos poids de modèle sont définitivement figés et que votre objectif est de réduire au maximum vos coûts d’exploitation sur du matériel NVIDIA moderne.</