Aller au contenu
Développement medium

SGLang : serveur d'inférence LLM et RadixAttention

14 min de lecture

SGLang est un moteur d'inférence pour servir un LLM sur GPU, concurrent direct de vLLM. Sa particularité est le RadixAttention : la réutilisation automatique du cache de préfixe entre requêtes, un atout décisif pour les charges multi-turn et RAG. Ce guide montre comment déployer SGLang avec Docker, l'interroger via son API compatible OpenAI, et le comparer à vLLM sur des mesures réelles. Public visé : ingénieurs plateforme et SRE disposant d'un GPU NVIDIA, déjà familiers du serving LLM. Les chiffres de ce guide ont été relevés sur un H100, dans des conditions identiques à celles du guide vLLM.

  • Comprendre ce que RadixAttention apporte par rapport au cache de préfixe classique.
  • Déployer SGLang avec Docker et son API compatible OpenAI.
  • Mesurer le débit et la latence avec le même protocole que vLLM.
  • Lire un comparatif chiffré SGLang contre vLLM sur un modèle 14B.
  • Savoir quand choisir SGLang plutôt que vLLM, et l'inverse.

SGLang exige un GPU NVIDIA, comme vLLM. Pour suivre ce guide, vous avez besoin de :

  • Un GPU NVIDIA architecture Ampere ou plus récente, avec assez de VRAM pour le modèle visé (environ 30 Go pour un modèle 14B en bfloat16).
  • Docker, le plugin Compose et le NVIDIA Container Toolkit installé.
  • Avoir lu le guide vLLM : SGLang partage avec lui les concepts de continuous batching et de PagedAttention, et l'installation du NVIDIA Container Toolkit y est détaillée.

Si les mécanismes de batching, de KV cache ou de RadixAttention sont flous, lisez d'abord Servir un LLM : batching et débit, qui les explique sans jargon. Pour situer SGLang dans l'écosystème, voir le comparatif des backends d'inférence.

SGLang et RadixAttention : la différence avec vLLM

Section intitulée « SGLang et RadixAttention : la différence avec vLLM »

SGLang et vLLM partagent les mêmes fondations : continuous batching pour garder le GPU occupé, KV cache paginé pour densifier la VRAM, API compatible OpenAI pour l'intégration. Sur un workload classique, leurs performances sont très proches — la section comparatif le montre chiffres à l'appui. La vraie différence tient à une optimisation propre à SGLang : le RadixAttention.

Le problème qu'il résout est courant. Dans un chatbot multi-turn, chaque nouveau message renvoie tout l'historique de la conversation. Dans un système RAG, chaque requête commence par le même system prompt et souvent les mêmes documents de contexte. Dans une flotte d'agents, tous partagent les mêmes instructions de base. À chaque fois, le modèle recalcule l'attention sur une portion de texte déjà traitée à la requête précédente — un gaspillage pur.

RadixAttention indexe les préfixes de tokens déjà calculés dans un arbre radix (une structure d'arbre où les branches partagent leurs débuts communs). Quand une nouvelle requête arrive, SGLang retrouve le plus long préfixe commun déjà en cache et réutilise son KV cache au lieu de le recalculer. La phase de prefill — l'ingestion du prompt — devient quasi gratuite pour la partie partagée.

L'image officielle lmsysorg/sglang embarque le serveur et toutes ses dépendances GPU. Comme pour vLLM, l'approche Docker évite toute installation de CUDA ou PyTorch sur l'hôte.

  1. Vérifier que Docker voit le GPU.

    Fenêtre de terminal
    docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi -L

    La sortie doit lister votre GPU. Si la commande échoue, c'est le NVIDIA Container Toolkit qui manque — voir le guide vLLM pour son installation.

  2. Décrire la stack dans un fichier compose.yml.

    Cet exemple sert Qwen2.5-14B-Instruct, sous licence Apache 2.0 et sans restriction d'accès sur Hugging Face.

    services:
    sglang:
    image: lmsysorg/sglang:latest
    container_name: sglang-server
    restart: unless-stopped
    runtime: nvidia
    ipc: host
    ports:
    - "30000:30000"
    volumes:
    - hf-cache:/root/.cache/huggingface
    command:
    - python3
    - -m
    - sglang.launch_server
    - --model-path
    - Qwen/Qwen2.5-14B-Instruct
    - --served-model-name
    - qwen2.5-14b
    - --host
    - "0.0.0.0"
    - --port
    - "30000"
    - --context-length
    - "8192"
    - --mem-fraction-static
    - "0.90"
    deploy:
    resources:
    reservations:
    devices:
    - driver: nvidia
    count: all
    capabilities: [gpu]
    healthcheck:
    test: ["CMD-SHELL", "curl -fsS http://localhost:30000/health || exit 1"]
    interval: 15s
    timeout: 5s
    retries: 40
    start_period: 600s
    volumes:
    hf-cache:

    Les paramètres ont leurs équivalents vLLM. --context-length correspond à --max-model-len : la longueur de contexte maximale. --mem-fraction-static correspond à --gpu-memory-utilization : la fraction de VRAM allouée au moteur. SGLang lance son serveur via le module Python sglang.launch_server.

  3. Démarrer le serveur et suivre le chargement.

    Fenêtre de terminal
    docker compose up -d
    docker compose logs -f sglang

    Le premier démarrage est long : téléchargement du modèle (~28 Go pour un 14B), chargement en VRAM puis capture des CUDA graphs. Les logs se terminent par The server is fired up and ready to roll!.

  4. Vérifier que le serveur est prêt.

    Fenêtre de terminal
    curl -fsS http://localhost:30000/health

    Une fois le modèle chargé, l'endpoint /health répond 200 OK et le healthcheck Docker passe à healthy.

SGLang expose la même API REST qu'OpenAI, sur le port 30000. L'endpoint /v1/models liste les modèles servis, /v1/chat/completions génère une réponse.

Fenêtre de terminal
curl -fsS http://localhost:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-14b",
"messages": [
{"role": "user", "content": "En une phrase, qu'\''est-ce que RadixAttention ?"}
],
"temperature": 0.2,
"max_tokens": 90
}'

Comme l'API est compatible, le SDK Python openai fonctionne en pointant base_url vers http://localhost:30000/v1. Tout code écrit pour vLLM, Ollama ou l'API OpenAI fonctionne sans modification : seule l'URL de base change. C'est ce qui rend les backends interchangeables et permet de les comparer à code constant.

Pour comparer deux moteurs honnêtement, il faut tout garder identique sauf le moteur. Les mesures ci-dessous ont été relevées sur la même machine (H100 PCIe 80 Go), le même modèle (Qwen2.5-14B-Instruct), le même contexte (8192) et avec le même outil de bench : vllm bench serve, qui sait interroger n'importe quelle API compatible OpenAI.

Fenêtre de terminal
docker run --rm --network host --entrypoint vllm vllm/vllm-openai:latest \
bench serve --backend openai --base-url http://localhost:30000 \
--endpoint /v1/completions \
--model qwen2.5-14b --tokenizer Qwen/Qwen2.5-14B-Instruct \
--dataset-name random --num-prompts 200 \
--random-input-len 1024 --random-output-len 256 --request-rate inf

Le conteneur de bench tourne sans GPU : il ne fait que des requêtes HTTP. Deux scénarios ont été mesurés — débit plafond (--request-rate inf, toutes les requêtes d'un coup) et charge modérée (--request-rate 8, arrivée progressive).

MesurevLLM 0.21SGLang 0.5
Débit total — débit plafond8 354 tok/s8 274 tok/s
TTFT médian — débit plafond7 983 ms6 995 ms
TPOT médian — débit plafond74,6 ms70,4 ms
Débit total — charge modérée7 916 tok/s7 920 tok/s
TTFT médian — charge modérée230 ms139 ms
TPOT médian — charge modérée53,2 ms53,5 ms

La lecture est nette : sur ce workload, vLLM et SGLang sont équivalents. Le débit total ne diffère que de moins de 1 %, et le TPOT (cadence de génération) est identique. SGLang garde un léger avantage sur le TTFT — 139 ms contre 230 ms à charge modérée — sans que cela bouleverse le choix.

Le bench le confirme : sur une charge sans préfixe partagé, le choix entre les deux est presque indifférent. La décision se joue ailleurs.

SGLang prend l'avantage quand votre charge présente une forte redondance de préfixe. Un chatbot où les conversations s'allongent tour après tour, un RAG avec un system prompt et des consignes fixes, une flotte d'agents partageant les mêmes instructions : dans tous ces cas, RadixAttention transforme un prefill répété en simple lecture de cache. Le gain est réel sur la latence et sur le débit effectif.

vLLM reste le choix par défaut pour un serving généraliste : sa communauté est plus large, son écosystème d'intégrations (LangChain, LlamaIndex, observabilité) plus mûr, et sa documentation plus fournie. Pour une charge hétérogène et sans structure de préfixe, rien ne justifie de quitter vLLM.

En pratique, la bonne démarche est de mesurer sur votre propre charge. Déployez les deux, rejouez vos prompts réels — pas un dataset aléatoire — et comparez le TTFT et le débit. C'est le seul comparatif qui engage votre production.

Les règles de sécurité sont identiques à celles de vLLM et tout aussi non négociables : exiger une clé d'API (option --api-key de sglang.launch_server), ne jamais exposer le port 30000 directement sur Internet, et placer le serveur derrière un reverse proxy qui termine le TLS. Un serveur d'inférence ouvert est une ressource GPU offerte à n'importe qui. Le guide vLLM détaille ce durcissement.

Côté incidents, les causes récurrentes au démarrage sont les mêmes que pour tout serveur GPU.

SymptômeCause probableSolution
CUDA out of memory au chargementModèle trop gros pour la VRAMBaisser --mem-fraction-static ou --context-length, ou répartir avec --tp-size
Démarrage très long la première foisTéléchargement du modèle + capture des CUDA graphsNormal ; le cache rend les démarrages suivants rapides
/health en 503 au débutModèle pas encore chargéAttendre ; le start_period du healthcheck couvre cette phase
GPU absent dans le conteneurNVIDIA Container Toolkit manquantInstaller le toolkit et relancer nvidia-ctk runtime configure
Conflit de VRAM avec un autre moteurvLLM et SGLang lancés ensembleN'en garder qu'un actif sur un GPU unique
Un cœur CPU à 100 % alors que le serveur est au reposScheduler SGLang en busy-loop (interrogation active de la file)Comportement normal et voulu ; ajouter --sleep-on-idle pour libérer le cœur quand aucune requête n'arrive
  • SGLang est un moteur d'inférence GPU, concurrent direct de vLLM, sous licence Apache 2.0.
  • Son atout distinctif est le RadixAttention : la réutilisation du cache de préfixe entre requêtes.
  • Sur un workload sans préfixe partagé, vLLM et SGLang sont équivalents (moins de 1 % d'écart de débit).
  • SGLang prend l'avantage sur les charges multi-turn, RAG et agents où les requêtes partagent un préfixe.
  • L'API compatible OpenAI rend les deux moteurs interchangeables : comparez-les à code constant sur votre charge réelle.
  • Sécurité identique à vLLM : clé d'API, reverse proxy, jamais d'exposition directe.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn