Ce qui se passe
vLLM détaille le 10 septembre son framework d'offloading étagé du cache KV, disponible depuis la version 0.22. Le problème : sur un modèle à long contexte ou en conversation multi-tours, le cache KV remplit la mémoire de l'accélérateur, les données les moins récentes sont évincées, et la requête suivante qui en a besoin les recalcule depuis zéro. Le framework conserve les blocs évincés dans des niveaux successifs et les recharge au lieu de les recalculer.
Comment ça marche
Le principe est host-centric : toute donnée KV passe par la mémoire de l'hôte.
- Libération immédiate. La copie accélérateur vers hôte est un transfert PCIe local ; la mémoire GPU est libérée dès qu'elle est finie, avant toute écriture disque ou réseau. Au rechargement, elle n'est allouée qu'une fois les données prêtes côté hôte.
- I/O consolidées. En tensor parallel, chaque GPU tient un fragment du cache ; le framework les rassemble dans une seule région hôte partagée, d'où des écritures moins nombreuses et plus grosses vers les niveaux secondaires.
- Format canonique. Chaque page hôte stocke un bloc d'une couche, toutes les têtes réunies. Comme ce format ne dépend pas de la configuration, un nœud en TP=2 et un nœud en TP=4 produisent les mêmes blocs et partagent leur cache sans conversion.
- Niveaux simples à écrire. Un niveau secondaire est un processus par
instance, avec des bibliothèques CPU standard, sans toucher à
l'accélérateur. L'interface tient en quatre méthodes (
lookup,submit_store,submit_load,get_finished_jobs), une implémentation de référence en mémoire est fournie, et un niveau externe se charge parmodule_pathsans modifier vLLM.
L'unité est le chunk, un bloc d'accélérateur par défaut, ajustable avec
blocks_per_chunk. Le cache hôte est un vrai cache LRU/ARC, pas un simple
tampon de passage.
Trois niveaux secondaires sont fournis : fs (un fichier par chunk, nommage par contenu, donc deux instances qui montent le même volume partagent leur cache sans configuration), obj (S3-compatible via NIXL, moins cher au Go) et p2p (coordination ZMQ, transfert RDMA d'hôte à hôte, pour la désagrégation prefill/decode ou l'équilibrage de charge). Les modèles hybrides sont pris en charge, couches à fenêtre glissante, MLA et Mamba comprises, avec DeepSeek V4, GLM 5.3 et Nemotron 3 cités.
vllm serve Qwen/Qwen3.6-35B-A3B \
--kv-transfer-config '{"kv_connector_extra_config": {
"spec_name": "TieringOffloadingSpec",
"cpu_bytes_to_use": 107374182400,
"secondary_tiers": [{"type": "fs", "root_dir": "/mnt/kv-cache"}]}}'Ce que ça donne
Mesure sur Qwen3.6-35B-A3B, deux H100, niveau fs sur NVMe local, conversations multi-tours de 12 000 tokens initiaux plus 4 000 par tour sur huit tours, 64 requêtes concurrentes au maximum :
- jusqu'à environ 64 conversations, la HBM tient tout et toutes les méthodes se valent ;
- entre 64 et 128, la HBM sature, le débit s'effondre sans offloading, et l'offloading CPU le maintient ;
- au-delà de 128, le cache CPU sature aussi, et le niveau stockage fait plus que doubler le débit.
Le stockage n'atteint jamais le débit de la RAM ; il gagne contre le recalcul
complet. Les scripts de reproduction sont publiés dans le dépôt
neuralmagic/fs-offload-experiments. Des métriques Prometheus par niveau
(remplissage, débit, latence, taux de hit) et des KV events alimentent des
orchestrateurs comme llm-d ou Dynamo, qui routent chaque requête vers
l'instance la plus susceptible d'avoir le cache.
À retenir
Un flag, une ligne de JSON et un répertoire sur NVMe suffisent pour essayer. Le gain n'apparaît qu'au-delà de ce que la HBM et la RAM contiennent ; en dessous, c'est de la complexité pour rien.
Source : Tiered KV Cache Offloading in vLLM