Tutorial LMCache: crea un livello di cache KV scalabile per l'inferenza LLM
Scopri come LMCache memorizza e riutilizza gli stati KV tra le richieste LLM, si integra con vLLM e riduce i calcoli di prefill ripetuti per l'inferenza con contesti lunghi.
L’inferenza dei modelli di grandi dimensioni può diventare sempre più costosa man mano che i prompt crescono.
I sistemi RAG, gli agenti di coding, i workflow multi-agente e le conversazioni lunghe spesso inviano più volte al modello gli stessi documenti, prompt di sistema, definizioni di tool o cronologia della conversazione.
Ogni volta che questo contesto condiviso viene elaborato durante il prefill, il modello genera stati key-value (KV) che vengono usati durante la generazione dei token.
Ricalcolare questi stati per lo stesso contesto spreca compute GPU e aumenta la latenza.
LMCache risolve questo problema aggiungendo un livello dedicato di cache KV allo stack di inferenza.
Può memorizzare stati KV calcolati in precedenza e renderli riutilizzabili tra richieste e worker di inferenza, supportando al contempo CPU, storage locale, backend remoti e architetture di serving disaggregato.
In questo tutorial ti mostrerò come funziona LMCache, in cosa differisce dal KV caching nativo di vLLM e dove si inseriscono, nel serving moderno degli LLM, funzionalità come lo storage multi-tier, la cache condivisa, CacheBlend e la disaggregazione prefill/decode.
Collegherai quindi LMCache a vLLM, servirai IBM Granite 4.2 3B ed eseguirai un esperimento controllato per misurare come il riuso di un ampio prefisso condiviso influenzi la latenza di inferenza.
Che cos’è LMCache?
LMCache è un livello di gestione della cache KV per l’inferenza LLM open source.
Consente di archiviare gli stati key-value creati durante il prefill e di riutilizzarli quando le richieste future condividono lo stesso prefisso del prompt.
Questo è diverso dal tradizionale caching delle risposte.
Una cache di risposte memorizza la risposta finale generata e la restituisce quando la stessa richiesta ricompare:
cache ={"What is Python?":"Python is a general-purpose programming language..."}Offerto da
LMCache agisce prima nel processo di inferenza. Invece di mettere in cache la risposta finale, archivia gli stati di attenzione KV prodotti mentre il modello elabora il prompt.
Per esempio, senza un KV caching riutilizzabile, un lungo prompt condiviso deve eseguire di nuovo il prefill ogni volta che si aggiunge una nuova domanda.
Con LMCache, la prima richiesta esegue il prefill completo e memorizza gli stati KV risultanti. Le richieste successive con lo stesso prefisso possono caricare quegli stati ed elaborare solo i token nuovi.
Fig. 1: Senza una cache KV riutilizzabile, l’intero prompt viene ricalcolato per ogni richiesta; con LMCache, gli stati KV in cache vengono riutilizzati e si elaborano solo i token nuovi.
Questo diventa sempre più prezioso man mano che crescono le finestre di contesto.
Rielaborare alcune centinaia di token può costare poco, ma processare ripetutamente decine di migliaia di token condivisi può aumentare sensibilmente la latenza e l’uso della GPU.
Come funziona LMCache
Il modo più semplice per capire LMCache è seguire due richieste che condividono lo stesso prefisso.
Per la prima richiesta, LMCache verifica se esistono già stati KV riutilizzabili. Poiché è la prima volta che il prompt viene visto, la ricerca porta a un mancato riscontro in cache.
vLLM quindi esegue il prefill sulla GPU, crea gli stati KV e li passa a LMCache per l’archiviazione.
Per la seconda richiesta, il prefisso condiviso resta lo stesso, ma la domanda cambia.
LMCache esegue un’altra ricerca. Questa volta il prefisso è già disponibile, risultando in un hit di cache. Gli stati in cache vengono riutilizzati e la GPU deve elaborare solo il suffisso non in cache.
Fig. 2: La prima richiesta con un nuovo prefisso manca la cache, quindi vLLM calcola il prefill e memorizza gli stati KV in LMCache; una richiesta ripetuta con lo stesso prefisso colpisce la cache e calcola solo il nuovo suffisso.
Il punto importante è che LMCache non richiede che l’intera richiesta sia identica. Conta il prefisso riutilizzabile.
Questo lo rende adatto ad applicazioni in cui il contesto di fondo resta uguale mentre cambia la query dell’utente.
Cache di prefissi vLLM vs LMCache
vLLM supporta già il caching automatico dei prefissi, quindi è legittimo chiedersi perché serva LMCache.
Entrambi gli approcci cercano di evitare di ricalcolare gli stati KV per i prefissi del prompt che il modello ha già elaborato.
La differenza principale è dove vive quella cache e quanto ampiamente può essere riutilizzata.
Funzionalità
KV caching nativo vLLM
LMCache
Riutilizzo KV di prefisso
Sì, tramite Automatic Prefix Caching
Sì
Riutilizzo KV non di prefisso
No
Sì, tramite CacheBlend
Cache KV su GPU
Sì
Funziona insieme alla cache KV su GPU di vLLM
Offloading KV su CPU
Sì
Sì
Storage SSD / NVMe
Supportato tramite livelli di storage secondari
Sì, incluso disco locale, NVMe e GDS
Storage remoto
Supporta opzioni come object storage compatibile S3
Supporta più backend tra cui Redis/Valkey, S3, Mooncake, InfiniStore, NIXL e altri
Condivisione cache cross-process
Supportata in alcune configurazioni, incluse P2P e storage condiviso
Funzione centrale, con più worker di inferenza che possono usare KV in cache condivise
Servizio di cache standalone
No, il caching è gestito come parte dello stack di serving di vLLM
Sì, la modalità MP di LMCache può girare indipendentemente da vLLM
Scalabilità indipendente della cache
Le risorse della cache sono in genere configurate con il deployment di inferenza
La capacità della cache può essere scalata separatamente dai worker vLLM
Disaggregazione prefill/decode
Supportata tramite connettori KV
Progettato specificamente per supportare il trasferimento KV tra worker di prefill e di decode
Ideale per
Riutilizzo efficiente dei prefissi e offloading KV all’interno di deployment vLLM
Carichi KV-cache su larga scala, condivisi, multi-tier o distribuiti
Il prefix caching integrato di vLLM è l’opzione più semplice quando le richieste ripetute sono gestite dallo stesso server di inferenza.
Se diverse richieste iniziano con gli stessi token, vLLM può riutilizzare i blocchi KV esistenti invece di eseguire di nuovo l’intero prefill.
LMCache estende questa idea oltre il motore di inferenza.
Invece di mantenere gli stati KV riutilizzabili solo nella cache di vLLM, LMCache introduce un livello di cache separato che può archiviare e spostare stati KV tra ulteriori livelli di storage e renderli disponibili a un’architettura di serving più ampia.
Un modo semplice per pensare alla differenza è:
Fig. 3: caching di prefissi vLLM vs LMCache. LMCache aggiunge un livello di caching che stratifica gli stati KV tra memoria CPU, SSD/NVMe locali e storage remoto invece della sola memoria GPU.
Quindi LMCache non sostituisce l’idea del KV caching in vLLM. Estende la gestione della KV-cache oltre i normali confini del motore di inferenza.
Funzionalità principali di LMCache
LMCache offre più di una semplice cache in memoria. È progettato per archiviare, spostare e riutilizzare stati KV tra diversi livelli di storage e worker di inferenza.
1. Riutilizzo della cache KV
La funzione principale di LMCache è la possibilità di riutilizzare stati KV calcolati in precedenza invece di far passare di nuovo gli stessi token attraverso il modello.
Questo è particolarmente utile quando le richieste includono ripetutamente lo stesso contesto o uno simile, come:
Documenti recuperati
Grandi prompt di sistema
Contesto del repository
Cronologia della conversazione
Definizioni di tool
Istruzioni condivise tra agenti
Riutilizzando stati KV in cache, LMCache può ridurre i calcoli di prefill ripetuti e migliorare il time to first token.
2. Storage multi-tier
La memoria GPU è limitata e costosa, soprattutto con contesti lunghi.
LMCache può spostare gli stati KV oltre la memoria GPU e archiviarli su più livelli, tra cui memoria CPU, storage locale SSD o NVMe e storage remoto o distribuito.
Questo rende possibile mantenere molto più contesto riutilizzabile di quanto potrebbe entrare interamente nella memoria GPU, riportando comunque in GPU gli stati KV usati di frequente quando servono.
3. Cache KV condivisa tra worker
LMCache può rendere disponibili gli stati KV in cache a più worker di inferenza invece di tenerli legati a un singolo processo del modello.
Per esempio, se un worker vLLM elabora un documento lungo, un altro worker può potenzialmente riutilizzare gli stati KV in cache invece di ricalcolare lo stesso contesto.
Questo è particolarmente utile per il serving distribuito, i deployment multi-GPU e le applicazioni in cui le richieste sono instradate su diverse repliche di inferenza.
4. Integrazione con vLLM
LMCache si integra con vLLM tramite la sua interfaccia di connettore KV.
L’applicazione può continuare a comunicare con il normale endpoint vLLM compatibile con OpenAI mentre LMCache opera sotto il livello di inferenza.
Questo significa che le applicazioni esistenti non devono cambiare il modo in cui inviano prompt o ricevono risposte. LMCache gestisce l’archiviazione e il recupero dei KV tra vLLM e il backend di cache configurato.
5. Architettura multiprocesso
LMCache può essere eseguito come processo separato da vLLM.
Invece di mantenere la gestione della cache all’interno di ciascun worker di inferenza, un server LMCache dedicato può gestire gli stati KV in modo indipendente e servire più processi vLLM.
Questo separa la gestione della cache dal serving del modello, consente a più worker di condividere la stessa cache e rende più semplice scalare la capacità di cache indipendentemente dalle risorse di inferenza GPU.
6. CacheBlend
Il caching tradizionale dei prefissi funziona al meglio quando le richieste condividono lo stesso inizio di prompt.
LMCache offre anche CacheBlend per carichi in cui il contenuto riutilizzabile può apparire in posizioni diverse.
Per esempio, un’applicazione RAG potrebbe recuperare gli stessi documenti in un ordine differente per domande diverse.
CacheBlend può riutilizzare parti di stati KV calcolati in precedenza, ricalcolando selettivamente i token che dipendono dal nuovo contesto.
Questo rende il riuso dei KV più utile per RAG, applicazioni multi-documento e workflow agentici in cui i prompt sono spesso riorganizzati.
7. Disaggregazione di prefill e decode
LMCache può anche aiutare a trasferire stati KV tra worker separati di prefill e di decode.
In questa architettura, un gruppo di GPU gestisce la fase di elaborazione del prompt, intensiva in termini di calcolo, mentre un altro gruppo gestisce la generazione dei token.
LMCache fornisce il livello usato per spostare tra loro gli stati KV risultanti.
Questo consente di scalare in modo indipendente le risorse di prefill e di decoding e può migliorare l’utilizzo della GPU in deployment di inferenza più grandi.
Primi passi con LMCache
Ora che sappiamo come funziona LMCache, colleghiamolo a vLLM, un motore di inferenza LLM ad alte prestazioni progettato per un serving e una gestione della memoria efficienti.
Per questa guida userò IBM Granite 4.2 3B, un modello compatto che offre prestazioni solide rispetto alle sue dimensioni, rimanendo abbastanza leggero per test pratici.
Eseguiremo LMCache in modalità multiprocesso insieme a vLLM e verificheremo che gli stati KV possano essere riutilizzati tra le richieste.
1. Configurazione dell’ambiente
Per questo tutorial useremo Python 3.12, uv, vLLM, LMCache, il client Python di OpenAI, pandas e matplotlib.
Prima di iniziare, assicurati di avere:
Una GPU NVIDIA con i driver appropriati installati
Il toolkit CUDA 13 installato e disponibile sul tuo sistema
uv installato
Puoi installare uv con:
curl-LsSf https://astral.sh/uv/install.sh |shOfferto da
Quindi crea il progetto:
mkdir lmcache-tutorial
cd lmcache-tutorialOfferto da
Crea e attiva un ambiente virtuale Python 3.12:
uv venv --python3.12source .venv/bin/activateOfferto da
3. Verifica di LMCache con un cache hit controllato
Ora eseguiremo un semplice esperimento controllato per confermare che LMCache stia funzionando.
Creeremo un ampio prefisso condiviso, svuoteremo la cache, invieremo il prefisso una volta per popolare LMCache e poi invieremo un’altra richiesta con lo stesso prefisso ma una domanda diversa.
Per prima cosa, crea il client OpenAI:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="local",)Offerto da
Poi crea un documento condiviso lungo:
base_text ="""
Large language model inference consists of two main stages:
prefill and decoding.
During prefill, the model processes the input sequence and calculates
the key and value tensors used by the attention mechanism.
During autoregressive decoding, these tensors are reused so the model
does not need to recompute attention states for every previous token.
KV cache management is therefore an important part of modern LLM
serving infrastructure, particularly for long-context applications.
"""
document = base_text *500
SYSTEM_PROMPT =f"""
You are a technical assistant.
Use only the following document to answer the user's question.
DOCUMENT:
{document}
"""Offerto da
Ripetere il documento 500 volte ci dà un ampio prefisso condiviso abbastanza costoso da rendere visibile l’effetto del riuso dei KV.
Prima di inviare la prima richiesta, svuota LMCache così da partire con una cache vuota:
import subprocess
import time
subprocess.run(["lmcache","kvcache","clear","--url","http://localhost:8081",],
check=True,)
time.sleep(0.5)Offerto da
Questo assicura che la prima richiesta sia una richiesta a cache fredda e non possa riutilizzare stati KV rimasti da un test precedente.
Ora invia la prima richiesta:
prompt_1 = SYSTEM_PROMPT +"""
Question:
Explain the purpose of the KV cache.
"""
start = time.perf_counter()
client.completions.create(
model="granite-4.2-3b",
prompt=prompt_1,
max_tokens=100,
temperature=0,)
latency_1 = time.perf_counter()- startOfferto da
Questa è la richiesta di riscaldamento della cache. vLLM deve elaborare l’ampio prefisso condiviso durante il prefill, mentre LMCache memorizza gli stati KV risultanti.
Poi, mantieni esattamente uguale il prefisso condiviso e cambia solo la domanda:
prompt_2 = SYSTEM_PROMPT +"""
Question:
Explain what happens during prefill.
"""
start = time.perf_counter()
client.completions.create(
model="granite-4.2-3b",
prompt=prompt_2,
max_tokens=100,
temperature=0,)
latency_2 = time.perf_counter()- startOfferto da
Poiché l’ampio prefisso è invariato, LMCache può riutilizzare gli stati KV generati dalla prima richiesta invece di ricalcolare di nuovo l’intero prefisso.
La richiesta calda è stata quasi 6× più veloce, riducendo la latenza end-to-end di 83,2%.
Le domande sono diverse, quindi LMCache non sta mettendo in cache la risposta finale. Sta invece riutilizzando gli stati KV generati per il prefisso condiviso.
La prima richiesta deve elaborare l’intero lungo prefisso durante il prefill e creare da zero quegli stati KV.
Nella seconda richiesta, LMCache recupera gli stati in cache corrispondenti, consentendo a vLLM di saltare gran parte di quel lavoro di prefill ripetuto e concentrarsi solo sul nuovo suffisso.
Questo conferma che LMCache sta riutilizzando correttamente il prefisso condiviso.
Quando è utile LMCache?
LMCache è particolarmente utile quando un’applicazione invia ripetutamente grandi quantità di contesto identico.
Alcuni esempi comuni sono:
Applicazioni RAG
Un utente può porre più domande sullo stesso documento recuperato.
Invece di elaborare l’intero documento da zero per ogni domanda, si possono riutilizzare i suoi stati KV.
Agenti di coding
Gli assistenti di coding inviano spesso file di repository, istruzioni di progetto e altri grandi pezzi di contesto a ogni chiamata del modello.
Gran parte di quel contesto resta identico mentre cambia il task.
Agenti AI
Gli agenti spesso riutilizzano ampi prompt di sistema, definizioni di tool, memoria, istruzioni e stato dell’ambiente in molti passaggi.
Conversazioni lunghe
Una conversazione di lunga durata può inviare ripetutamente una parte sostanziale della sua cronologia a ogni nuovo messaggio.
Sistemi multi-agente
Più agenti possono condividere gli stessi documenti di background o contesto di sistema mentre lavorano su task diversi.
In tutti questi casi, al modello viene mostrata ripetutamente un’informazione che ha già elaborato in richieste precedenti.
LMCache offre un modo per riutilizzare quel lavoro a livello di KV-cache.
Considerazioni finali
LMCache affronta una grande fonte di spreco nell’inferenza con contesti lunghi rendendo riutilizzabili gli stati KV creati durante il prefill.
Invece di elaborare più e più volte lo stesso contesto condiviso, il modello può riutilizzare il lavoro già fatto.
Non abbiamo incluso in questo tutorial il codice di benchmark o i risultati dettagliati, ma abbiamo eseguito un set separato di test con la stessa configurazione.
I risultati sono stati significativi. Il riuso di un grande prefisso condiviso ha ridotto la latenza totale della richiesta da 26,276 secondi a 4,386 secondi.
Il tempo medio al primo token è passato da 22,149 secondi a 0,726 secondi, un miglioramento di 30,54×. I guadagni sono cresciuti anche con la dimensione del contesto, da 3,55× con circa 12.000 caratteri condivisi a 30,22× con circa 245.000 caratteri.
In parole semplici, più contesto si può riutilizzare, più lavoro LMCache può evitare.
DeepSeek è un buon esempio reale del perché questo conta.
Il suo sistema di caching può riutilizzare prefissi di prompt corrispondenti, cosa particolarmente preziosa per agenti di coding che inviano ripetutamente gli stessi prompt di sistema, tool, cronologia delle conversazioni e contesto di codice.
Tassi di hit più alti significano meno calcoli ripetuti e costi inferiori sia per il provider sia per l’utente.
La lezione principale di questa guida è che rendere più veloce l’inferenza LLM non significa solo avere GPU migliori o generazione di token più rapida. Significa anche non ripetere lavoro inutilmente.
Per i sistemi RAG, gli assistenti di coding, gli agenti e altre applicazioni con contesti lunghi, il KV caching riutilizzabile può essere una parte importante per migliorare la latenza, ridurre l’uso della GPU e abbassare i costi di inferenza.
FAQs
LMCache funziona solo con vLLM?⌄
Anche se LMCache è profondamente integrato con vLLM tramite il suo connettore KV, non è esclusivo di vLLM. L’architettura funge da middleware di caching e attualmente supporta altri popolari motori di inferenza LLM come SGLang, con supporto nativo per TensorRT-LLM in sviluppo attivo.
Quali backend di storage remoto sono supportati da LMCache?⌄
Oltre alla normale RAM della CPU e agli SSD/drive NVMe locali, LMCache supporta un’ampia varietà di sistemi di storage remoti e distribuiti.Puoi collegare LMCache a Redis/Valkey, object storage compatibile S3, Mooncake, NIXL e InfiniStore, permettendoti di scalare il tuo pool di cache KV su architetture distribuite.
Come gestisce LMCache i limiti di storage quando la cache si riempie?⌄
LMCache usa politiche di eviction configurabili per determinare quali stati KV eliminare quando si raggiungono i limiti di memoria CPU, disco locale o storage remoto.La politica predefinita è Least Recently Used (LRU), ma puoi configurare facilmente il sistema per usare Least Frequently Used (LFU) o First-In-First-Out (FIFO) in base ai pattern di accesso della tua applicazione.
LMCache può archiviare cache KV quantizzate come FP8?⌄
Sì, LMCache gestisce senza problemi dati di cache KV quantizzati.Se il tuo motore di inferenza è configurato per usare una cache KV quantizzata—ad esempio FP8—LMCache memorizzerà e trasferirà i chunk in quel formato compresso. Questo riduce drasticamente l’ingombro di storage e abbassa la banda di memoria necessaria per spostare gli stati KV tra i vari tier hardware.
Ci sono rischi di sicurezza quando si condivide una cache KV tra più utenti?⌄
In deployment multi-tenant o API pubbliche, condividere una cache KV può introdurre vulnerabilità di side-channel temporale.Poiché gli hit di cache rispondono significativamente più in fretta dei calcoli di prefill a freddo, un utente malevolo potrebbe potenzialmente sondare i pattern di latenza per dedurre parti del prompt privato di un altro utente. Per ambienti zero-trust, gli architetti di sistema devono implementare una rigorosa isolazione dei tenant o disabilitare del tutto la condivisione della cache tra tenant.
In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
L’inferenza dei modelli di grandi dimensioni può diventare sempre più costosa man mano che i prompt crescono.
I sistemi RAG, gli agenti di coding, i workflow multi-agente e le conversazioni lunghe spesso inviano più volte al modello gli stessi documenti, prompt di sistema, definizioni di tool o cronologia della conversazione.
Ogni volta che questo contesto condiviso viene elaborato durante il prefill, il modello genera stati key-value (KV) che vengono usati durante la generazione dei token.
Ricalcolare questi stati per lo stesso contesto spreca compute GPU e aumenta la latenza.
LMCache risolve questo problema aggiungendo un livello dedicato di cache KV allo stack di inferenza.
Può memorizzare stati KV calcolati in precedenza e renderli riutilizzabili tra richieste e worker di inferenza, supportando al contempo CPU, storage locale, backend remoti e architetture di serving disaggregato.
In questo tutorial ti mostrerò come funziona LMCache, in cosa differisce dal KV caching nativo di vLLM e dove si inseriscono, nel serving moderno degli LLM, funzionalità come lo storage multi-tier, la cache condivisa, CacheBlend e la disaggregazione prefill/decode.
Collegherai quindi LMCache a vLLM, servirai IBM Granite 4.2 3B ed eseguirai un esperimento controllato per misurare come il riuso di un ampio prefisso condiviso influenzi la latenza di inferenza.
Che cos’è LMCache?
LMCache è un livello di gestione della cache KV per l’inferenza LLM open source.
Consente di archiviare gli stati key-value creati durante il prefill e di riutilizzarli quando le richieste future condividono lo stesso prefisso del prompt.
Fonte: LMCache – Building the foundation of AI memory tensor with KV Cache Infrastructure
Questo è diverso dal tradizionale caching delle risposte.
Una cache di risposte memorizza la risposta finale generata e la restituisce quando la stessa richiesta ricompare:
LMCache agisce prima nel processo di inferenza. Invece di mettere in cache la risposta finale, archivia gli stati di attenzione KV prodotti mentre il modello elabora il prompt.
Per esempio, senza un KV caching riutilizzabile, un lungo prompt condiviso deve eseguire di nuovo il prefill ogni volta che si aggiunge una nuova domanda.
Con LMCache, la prima richiesta esegue il prefill completo e memorizza gli stati KV risultanti. Le richieste successive con lo stesso prefisso possono caricare quegli stati ed elaborare solo i token nuovi.
Fig. 1: Senza una cache KV riutilizzabile, l’intero prompt viene ricalcolato per ogni richiesta; con LMCache, gli stati KV in cache vengono riutilizzati e si elaborano solo i token nuovi.
Questo diventa sempre più prezioso man mano che crescono le finestre di contesto.
Rielaborare alcune centinaia di token può costare poco, ma processare ripetutamente decine di migliaia di token condivisi può aumentare sensibilmente la latenza e l’uso della GPU.
Come funziona LMCache
Il modo più semplice per capire LMCache è seguire due richieste che condividono lo stesso prefisso.
Per la prima richiesta, LMCache verifica se esistono già stati KV riutilizzabili. Poiché è la prima volta che il prompt viene visto, la ricerca porta a un mancato riscontro in cache.
vLLM quindi esegue il prefill sulla GPU, crea gli stati KV e li passa a LMCache per l’archiviazione.
Per la seconda richiesta, il prefisso condiviso resta lo stesso, ma la domanda cambia.
LMCache esegue un’altra ricerca. Questa volta il prefisso è già disponibile, risultando in un hit di cache. Gli stati in cache vengono riutilizzati e la GPU deve elaborare solo il suffisso non in cache.
Fig. 2: La prima richiesta con un nuovo prefisso manca la cache, quindi vLLM calcola il prefill e memorizza gli stati KV in LMCache; una richiesta ripetuta con lo stesso prefisso colpisce la cache e calcola solo il nuovo suffisso.
Il punto importante è che LMCache non richiede che l’intera richiesta sia identica. Conta il prefisso riutilizzabile.
Questo lo rende adatto ad applicazioni in cui il contesto di fondo resta uguale mentre cambia la query dell’utente.
Cache di prefissi vLLM vs LMCache
vLLM supporta già il caching automatico dei prefissi, quindi è legittimo chiedersi perché serva LMCache.
Entrambi gli approcci cercano di evitare di ricalcolare gli stati KV per i prefissi del prompt che il modello ha già elaborato.
La differenza principale è dove vive quella cache e quanto ampiamente può essere riutilizzata.
Funzionalità
KV caching nativo vLLM
LMCache
Riutilizzo KV di prefisso
Sì, tramite Automatic Prefix Caching
Sì
Riutilizzo KV non di prefisso
No
Sì, tramite CacheBlend
Cache KV su GPU
Sì
Funziona insieme alla cache KV su GPU di vLLM
Offloading KV su CPU
Sì
Sì
Storage SSD / NVMe
Supportato tramite livelli di storage secondari
Sì, incluso disco locale, NVMe e GDS
Storage remoto
Supporta opzioni come object storage compatibile S3
Supporta più backend tra cui Redis/Valkey, S3, Mooncake, InfiniStore, NIXL e altri
Condivisione cache cross-process
Supportata in alcune configurazioni, incluse P2P e storage condiviso
Funzione centrale, con più worker di inferenza che possono usare KV in cache condivise
Servizio di cache standalone
No, il caching è gestito come parte dello stack di serving di vLLM
Sì, la modalità MP di LMCache può girare indipendentemente da vLLM
Scalabilità indipendente della cache
Le risorse della cache sono in genere configurate con il deployment di inferenza
La capacità della cache può essere scalata separatamente dai worker vLLM
Disaggregazione prefill/decode
Supportata tramite connettori KV
Progettato specificamente per supportare il trasferimento KV tra worker di prefill e di decode
Ideale per
Riutilizzo efficiente dei prefissi e offloading KV all’interno di deployment vLLM
Carichi KV-cache su larga scala, condivisi, multi-tier o distribuiti
Il prefix caching integrato di vLLM è l’opzione più semplice quando le richieste ripetute sono gestite dallo stesso server di inferenza.
Se diverse richieste iniziano con gli stessi token, vLLM può riutilizzare i blocchi KV esistenti invece di eseguire di nuovo l’intero prefill.
LMCache estende questa idea oltre il motore di inferenza.
Invece di mantenere gli stati KV riutilizzabili solo nella cache di vLLM, LMCache introduce un livello di cache separato che può archiviare e spostare stati KV tra ulteriori livelli di storage e renderli disponibili a un’architettura di serving più ampia.
Un modo semplice per pensare alla differenza è:
Fig. 3: caching di prefissi vLLM vs LMCache. LMCache aggiunge un livello di caching che stratifica gli stati KV tra memoria CPU, SSD/NVMe locali e storage remoto invece della sola memoria GPU.
Quindi LMCache non sostituisce l’idea del KV caching in vLLM. Estende la gestione della KV-cache oltre i normali confini del motore di inferenza.
Funzionalità principali di LMCache
LMCache offre più di una semplice cache in memoria. È progettato per archiviare, spostare e riutilizzare stati KV tra diversi livelli di storage e worker di inferenza.
1. Riutilizzo della cache KV
La funzione principale di LMCache è la possibilità di riutilizzare stati KV calcolati in precedenza invece di far passare di nuovo gli stessi token attraverso il modello.
Questo è particolarmente utile quando le richieste includono ripetutamente lo stesso contesto o uno simile, come:
Riutilizzando stati KV in cache, LMCache può ridurre i calcoli di prefill ripetuti e migliorare il time to first token.
2. Storage multi-tier
La memoria GPU è limitata e costosa, soprattutto con contesti lunghi.
LMCache può spostare gli stati KV oltre la memoria GPU e archiviarli su più livelli, tra cui memoria CPU, storage locale SSD o NVMe e storage remoto o distribuito.
Questo rende possibile mantenere molto più contesto riutilizzabile di quanto potrebbe entrare interamente nella memoria GPU, riportando comunque in GPU gli stati KV usati di frequente quando servono.
3. Cache KV condivisa tra worker
LMCache può rendere disponibili gli stati KV in cache a più worker di inferenza invece di tenerli legati a un singolo processo del modello.
Per esempio, se un worker vLLM elabora un documento lungo, un altro worker può potenzialmente riutilizzare gli stati KV in cache invece di ricalcolare lo stesso contesto.
Questo è particolarmente utile per il serving distribuito, i deployment multi-GPU e le applicazioni in cui le richieste sono instradate su diverse repliche di inferenza.
4. Integrazione con vLLM
LMCache si integra con vLLM tramite la sua interfaccia di connettore KV.
L’applicazione può continuare a comunicare con il normale endpoint vLLM compatibile con OpenAI mentre LMCache opera sotto il livello di inferenza.
Questo significa che le applicazioni esistenti non devono cambiare il modo in cui inviano prompt o ricevono risposte. LMCache gestisce l’archiviazione e il recupero dei KV tra vLLM e il backend di cache configurato.
5. Architettura multiprocesso
LMCache può essere eseguito come processo separato da vLLM.
Invece di mantenere la gestione della cache all’interno di ciascun worker di inferenza, un server LMCache dedicato può gestire gli stati KV in modo indipendente e servire più processi vLLM.
Questo separa la gestione della cache dal serving del modello, consente a più worker di condividere la stessa cache e rende più semplice scalare la capacità di cache indipendentemente dalle risorse di inferenza GPU.
6. CacheBlend
Il caching tradizionale dei prefissi funziona al meglio quando le richieste condividono lo stesso inizio di prompt.
LMCache offre anche CacheBlend per carichi in cui il contenuto riutilizzabile può apparire in posizioni diverse.
Per esempio, un’applicazione RAG potrebbe recuperare gli stessi documenti in un ordine differente per domande diverse.
CacheBlend può riutilizzare parti di stati KV calcolati in precedenza, ricalcolando selettivamente i token che dipendono dal nuovo contesto.
Questo rende il riuso dei KV più utile per RAG, applicazioni multi-documento e workflow agentici in cui i prompt sono spesso riorganizzati.
7. Disaggregazione di prefill e decode
LMCache può anche aiutare a trasferire stati KV tra worker separati di prefill e di decode.
In questa architettura, un gruppo di GPU gestisce la fase di elaborazione del prompt, intensiva in termini di calcolo, mentre un altro gruppo gestisce la generazione dei token.
LMCache fornisce il livello usato per spostare tra loro gli stati KV risultanti.
Questo consente di scalare in modo indipendente le risorse di prefill e di decoding e può migliorare l’utilizzo della GPU in deployment di inferenza più grandi.
Primi passi con LMCache
Ora che sappiamo come funziona LMCache, colleghiamolo a vLLM, un motore di inferenza LLM ad alte prestazioni progettato per un serving e una gestione della memoria efficienti.
Per questa guida userò IBM Granite 4.2 3B, un modello compatto che offre prestazioni solide rispetto alle sue dimensioni, rimanendo abbastanza leggero per test pratici.
Eseguiremo LMCache in modalità multiprocesso insieme a vLLM e verificheremo che gli stati KV possano essere riutilizzati tra le richieste.
1. Configurazione dell’ambiente
Per questo tutorial useremo Python 3.12, uv, vLLM, LMCache, il client Python di OpenAI, pandas e matplotlib.
Prima di iniziare, assicurati di avere:
Puoi installare
uvcon:Quindi crea il progetto:
Crea e attiva un ambiente virtuale Python 3.12:
Installa le dipendenze richieste:
Qui usiamo
cu130perché il nostro ambiente è configurato con CUDA 13.Se usi una versione CUDA diversa, cambia il valore di
--torch-backendcon il backend PyTorch compatibile per il tuo ambiente.Granite 4.2 usa un parser di reasoning personalizzato, quindi scaricalo da Hugging Face:
Infine, verifica che la tua GPU e l’installazione di CUDA siano rilevate:
Per questo tutorial usiamo una NVIDIA GeForce RTX 5070 Ti con 16 GB di VRAM.
Il sistema esegue il driver NVIDIA 580.126.09, con supporto CUDA 13.0.
2. Avvia vLLM con LMCache
Ci servono due processi in esecuzione: uno per il server LMCache e un altro per vLLM.
Avvia LMCache nel primo terminale:
Qui usiamo:
6555per la comunicazione tra vLLM e LMCache8081per l’interfaccia HTTP di LMCache20 GBper la cache L1LRUcome politica di evictionLascia questo terminale in esecuzione.
Apri un secondo terminale, attiva lo stesso ambiente virtuale e disattiva la configurazione dell’allocatore CUDA espandibile se è abilitata:
Ora avvia vLLM con il connettore LMCache:
Disabilitiamo il prefix caching integrato di vLLM con:
Questo consente ai seguenti esperimenti di concentrarsi specificamente sul riuso dei KV tramite LMCache.
Una volta che vLLM ha terminato il caricamento, il modello è disponibile tramite il suo endpoint compatibile con OpenAI:
3. Verifica di LMCache con un cache hit controllato
Ora eseguiremo un semplice esperimento controllato per confermare che LMCache stia funzionando.
Creeremo un ampio prefisso condiviso, svuoteremo la cache, invieremo il prefisso una volta per popolare LMCache e poi invieremo un’altra richiesta con lo stesso prefisso ma una domanda diversa.
Per prima cosa, crea il client OpenAI:
Poi crea un documento condiviso lungo:
Ripetere il documento 500 volte ci dà un ampio prefisso condiviso abbastanza costoso da rendere visibile l’effetto del riuso dei KV.
Prima di inviare la prima richiesta, svuota LMCache così da partire con una cache vuota:
Questo assicura che la prima richiesta sia una richiesta a cache fredda e non possa riutilizzare stati KV rimasti da un test precedente.
Ora invia la prima richiesta:
Questa è la richiesta di riscaldamento della cache. vLLM deve elaborare l’ampio prefisso condiviso durante il prefill, mentre LMCache memorizza gli stati KV risultanti.
Poi, mantieni esattamente uguale il prefisso condiviso e cambia solo la domanda:
Poiché l’ampio prefisso è invariato, LMCache può riutilizzare gli stati KV generati dalla prima richiesta invece di ricalcolare di nuovo l’intero prefisso.
Infine, confronta i tempi delle due richieste:
La mia esecuzione ha prodotto:
La richiesta calda è stata quasi 6× più veloce, riducendo la latenza end-to-end di 83,2%.
Le domande sono diverse, quindi LMCache non sta mettendo in cache la risposta finale. Sta invece riutilizzando gli stati KV generati per il prefisso condiviso.
La prima richiesta deve elaborare l’intero lungo prefisso durante il prefill e creare da zero quegli stati KV.
Nella seconda richiesta, LMCache recupera gli stati in cache corrispondenti, consentendo a vLLM di saltare gran parte di quel lavoro di prefill ripetuto e concentrarsi solo sul nuovo suffisso.
Questo conferma che LMCache sta riutilizzando correttamente il prefisso condiviso.
Quando è utile LMCache?
LMCache è particolarmente utile quando un’applicazione invia ripetutamente grandi quantità di contesto identico.
Alcuni esempi comuni sono:
Applicazioni RAG
Un utente può porre più domande sullo stesso documento recuperato.
Invece di elaborare l’intero documento da zero per ogni domanda, si possono riutilizzare i suoi stati KV.
Agenti di coding
Gli assistenti di coding inviano spesso file di repository, istruzioni di progetto e altri grandi pezzi di contesto a ogni chiamata del modello.
Gran parte di quel contesto resta identico mentre cambia il task.
Agenti AI
Gli agenti spesso riutilizzano ampi prompt di sistema, definizioni di tool, memoria, istruzioni e stato dell’ambiente in molti passaggi.
Conversazioni lunghe
Una conversazione di lunga durata può inviare ripetutamente una parte sostanziale della sua cronologia a ogni nuovo messaggio.
Sistemi multi-agente
Più agenti possono condividere gli stessi documenti di background o contesto di sistema mentre lavorano su task diversi.
In tutti questi casi, al modello viene mostrata ripetutamente un’informazione che ha già elaborato in richieste precedenti.
LMCache offre un modo per riutilizzare quel lavoro a livello di KV-cache.
Considerazioni finali
LMCache affronta una grande fonte di spreco nell’inferenza con contesti lunghi rendendo riutilizzabili gli stati KV creati durante il prefill.
Invece di elaborare più e più volte lo stesso contesto condiviso, il modello può riutilizzare il lavoro già fatto.
Non abbiamo incluso in questo tutorial il codice di benchmark o i risultati dettagliati, ma abbiamo eseguito un set separato di test con la stessa configurazione.
I risultati sono stati significativi. Il riuso di un grande prefisso condiviso ha ridotto la latenza totale della richiesta da 26,276 secondi a 4,386 secondi.
Il tempo medio al primo token è passato da 22,149 secondi a 0,726 secondi, un miglioramento di 30,54×. I guadagni sono cresciuti anche con la dimensione del contesto, da 3,55× con circa 12.000 caratteri condivisi a 30,22× con circa 245.000 caratteri.
In parole semplici, più contesto si può riutilizzare, più lavoro LMCache può evitare.
DeepSeek è un buon esempio reale del perché questo conta.
Il suo sistema di caching può riutilizzare prefissi di prompt corrispondenti, cosa particolarmente preziosa per agenti di coding che inviano ripetutamente gli stessi prompt di sistema, tool, cronologia delle conversazioni e contesto di codice.
Tassi di hit più alti significano meno calcoli ripetuti e costi inferiori sia per il provider sia per l’utente.
La lezione principale di questa guida è che rendere più veloce l’inferenza LLM non significa solo avere GPU migliori o generazione di token più rapida. Significa anche non ripetere lavoro inutilmente.
Per i sistemi RAG, gli assistenti di coding, gli agenti e altre applicazioni con contesti lunghi, il KV caching riutilizzabile può essere una parte importante per migliorare la latenza, ridurre l’uso della GPU e abbassare i costi di inferenza.