KV cache: la memoria de trabajo que sostiene la inferencia LLM
TL;DR
El KV cache es la memoria de trabajo que un modelo de lenguaje mantiene durante una conversación. Sin él, cada token nuevo obligaría a recalcular toda la conversación desde el principio, con un coste cuadrático en la longitud del texto. Con él, el coste es lineal pero a cambio el cache vive en VRAM y crece con cada token. En la práctica, no es el modelo lo que limita cuánto contexto puedes servir: es el KV cache. Para una RTX 4090 con Llama 3 8B, cabe el modelo en 16 GB y queda apenas espacio para ~64 K tokens de cache totales (sumando todas las sesiones simultáneas). Entender este número es la diferencia entre prometerle a un cliente “contexto de 128 K” y entregárselo.
Estás aquí: Deploy
Este post abre la serie de fundamentos de inferencia LLM. Dentro del pipeline LLMOps de seis etapas que articula todo el sistema, el KV cache vive en la etapa Deploy: es la pieza que dicta cuánto tráfico cabe en tu motor de inferencia y, por tanto, cuánta plataforma puedes ofrecer encima.
La analogía: el orador con amnesia
Imagina que asistes a una conferencia técnica de dos horas. El ponente, cada vez que va a decir una frase nueva, rebobina mentalmente toda la charla desde el inicio, recompone el hilo, y solo entonces continúa. Su próxima frase requiere rememorar la anterior; la siguiente, las dos anteriores; al cabo de una hora, cada palabra nueva le cuesta una hora de recapitulación. Una conferencia así sería materialmente imposible.
Ahora imagina al mismo ponente con un cuaderno donde apunta, mientras habla, las dos o tres ideas clave de cada frase: sujeto, objeto, vínculo con lo anterior. Antes de cada frase nueva, ojea el cuaderno y sigue. Su próxima palabra sólo cuesta una ojeada al cuaderno, no rebobinar la charla entera.
Ese cuaderno, en un transformer, se llama KV cache. Sin él, los modelos de lenguaje conversacionales serían inviables. Con él, son productos comerciales. Pero el cuaderno pesa: y entender cuánto, dónde y por qué, es lo que separa una infraestructura de inferencia que funciona de una que se cae al tercer cliente concurrente.
El mecanismo en sí (en cristiano)
Un transformer genera texto un token cada vez. Para decidir el siguiente token, el modelo aplica un mecanismo llamado atención sobre todos los tokens previos: pregunta “¿qué partes del contexto anterior son relevantes para predecir lo que viene ahora?”.
Internamente, cada token de entrada se proyecta a tres vectores:
- Q (Query): “qué estoy buscando”
- K (Key): “qué oferta este token”
- V (Value): “qué información lleva este token”
La atención del token actual contra el contexto se calcula multiplicando su Q contra las K de todos los tokens previos, normalizando con softmax, y ponderando las V correspondientes. Resultado: una representación contextualizada del token actual.
Aquí está la clave: para predecir el token N, sólo necesito Q nuevo (el del token N) y K, V de todos los tokens anteriores. Las K y V de los tokens 1..N-1 no han cambiado desde la iteración anterior. Recalcularlas sería tirar trabajo.
El KV cache es exactamente eso: la memoria que guarda K y V de cada token ya procesado, en cada capa del modelo, para no recalcularlos.
Por qué existe: el coste cuadrático sin él
Generar un texto de N tokens implica N pasos. En el paso i, se calcula la atención sobre i tokens anteriores. Sin cache, en cada paso recomputas las K, V de los i-1 tokens anteriores más las del nuevo. La cuenta total de cómputos de atención crece como:
$$\sum_{i=1}^{N} i = \frac{N(N+1)}{2} \approx \frac{N^2}{2}$$
Con KV cache, sólo procesas el token nuevo en cada paso: coste lineal en N.
Los números concretos son demoledores:
| Tokens generados | Sin KV cache (operaciones) | Con KV cache | Ratio |
|---|---|---|---|
| 128 | 8 256 | 128 | 64× |
| 1 024 | 524 800 | 1 024 | 512× |
| 4 096 | 8 390 656 | 4 096 | 2 048× |
| 32 768 | 536 887 296 | 32 768 | 16 384× |
A los 32 K tokens, el cache te ahorra cuatro órdenes de magnitud de cómputo. No es una optimización: es lo que hace que la inferencia conversacional sea posible.
El precio: cuánto pesa la mochila
El KV cache se paga en VRAM. La fórmula, por secuencia, es:
KV_size = 2 · n_layers · n_kv_heads · head_dim · context_len · bytes_per_param
↑
K y V
Por token (sin el context_len), es una constante propia del modelo. Veamos números reales:
| Modelo | n_layers | n_kv_heads | head_dim | Bytes/token (BF16) | GB a 8 K ctx | GB a 32 K | GB a 128 K |
|---|---|---|---|---|---|---|---|
| Llama 3 8B (MHA hipotético) | 32 | 32 | 128 | 524 288 | 4.00 | 16.00 | 64.00 |
| Llama 3 8B (GQA real) | 32 | 8 | 128 | 131 072 | 1.00 | 4.00 | 16.00 |
| Llama 3 70B (GQA) | 80 | 8 | 128 | 327 680 | 2.50 | 10.00 | 40.00 |
| Qwen3 8B (GQA) | 36 | 8 | 128 | 147 456 | 1.12 | 4.50 | 18.00 |
| Mistral 7B (GQA) | 32 | 8 | 128 | 131 072 | 1.00 | 4.00 | 16.00 |
Dos lecturas inmediatas:
- Sin GQA, no hay 128 K que valga. Un Llama 3 8B con atención multi-head clásica necesitaría 64 GB sólo de KV cache para una única secuencia con 128 K tokens. Es decir, no cabe en ninguna GPU consumer. Por eso Meta, Mistral y compañía adoptaron Grouped Query Attention.
- El KV cache puede ser mayor que el modelo. Llama 3 8B BF16 ocupa ~16 GB. Con 128 K de contexto, su cache son otros 16 GB. Una sola sesión empata al modelo en VRAM.
La línea roja punteada marca la VRAM realista disponible en una RTX 4090 después de cargar el modelo. Cualquier modelo cuya curva cruza esa línea no podrá servir ese contexto sin estrategias adicionales (cuantización del cache, offload, particionado).
La inferencia es memory-bound, no compute-bound
Hay un equívoco común: pensar que “GPU rápida = inferencia rápida”. En el régimen donde realmente operan los servicios de inferencia con KV cache, lo que se mide es el ancho de banda de memoria. Cada token nuevo exige leer las K y V de todos los tokens anteriores desde HBM. El cómputo es modesto; el movimiento de datos, masivo.
Por eso, una H100 SXM (3.35 TB/s de HBM3) puede ser 2–3× más rápida que una A100 (1.55–2 TB/s) sin que la frecuencia ni el número de cores expliquen del todo la diferencia. Lo explica el ancho de banda.
Y por eso, también, las ofertas de “GPU baratas con mucha VRAM pero HBM lenta” (algunas variantes con GDDR6 o LPDDR5) decepcionan en inferencia con contextos largos: tienen sitio para guardar el cache pero les cuesta una eternidad releerlo.
Trucos para que el cuaderno sea más fino
Tres técnicas, en orden cronológico, han ido aplanando el tamaño del KV cache:
Multi-Head Attention (MHA). El planteamiento original del transformer (Vaswani et al., 2017). Cada cabeza de atención tiene su propia K y V. Caro en cache pero teóricamente máximo en expresividad. Es lo que tenían los modelos hasta ~2023.
Multi-Query Attention (MQA). Una sola K y V compartida por todas las cabezas. Reduce el cache n_heads veces. Funciona razonablemente pero degrada calidad de generación en algunos benchmarks.
Grouped Query Attention (GQA). El término medio que ha ganado. Las cabezas se agrupan: en Llama 3 8B, 32 cabezas de query comparten K, V en grupos de 4 → 8 grupos de KV. Reduce el cache 4× respecto a MHA con casi idéntica calidad. Es el estándar de facto desde 2024.
Multi-Head Latent Attention (MLA). La innovación de DeepSeek-V2/V3: en vez de almacenar K, V por cabeza, comprime el estado en un vector latente más pequeño y proyecta a K, V en el momento. El cache puede llegar a 70 bytes/token, dos órdenes de magnitud menos que GQA. Es la razón principal por la que DeepSeek-V3 (671 B parámetros, 37 B activos) es servible en infraestructura abordable.
Nota: la barra de MLA es ilustrativa con valores típicos publicados por DeepSeek; la implementación exacta depende del tamaño latente. Lo importante es el orden de magnitud.
A esto se suma una cuarta técnica ortogonal: cuantizar el cache a FP8, INT8 o incluso INT4. vLLM y TensorRT-LLM ya lo soportan en producción. Pasar de BF16 (2 bytes) a FP8 (1 byte) divide el cache por dos con coste pequeño en calidad. Pasar a INT4, por cuatro, con coste algo mayor.
El siguiente dragón: la fragmentación
Hasta aquí hemos hablado del cache como si fuera un bloque contiguo. En la práctica, un servidor de inferencia atiende decenas de sesiones simultáneas, cada una con su propio cache que crece a un ritmo distinto. La asignación naïve —reservar el máximo posible por sesión— desperdicia entre el 60 % y el 80 % de la VRAM según el paper original de PagedAttention.
PagedAttention —la idea de Kwon et al. (2023) que dio origen a vLLM— resuelve esto pidiendo prestada una técnica de los sistemas operativos: dividir la VRAM en bloques pequeños (típicamente de 16 tokens) y mantener una tabla de páginas lógicas → físicas por sesión. Una sesión ya no reserva un bloque contiguo enorme: crece un bloque cada vez, y los bloques pueden estar dispersos por la VRAM. Resultado: ocupación efectiva del 90 % en lugar del 30 %, y por tanto 2–4× más throughput agregado en el mismo hardware.
PagedAttention merece artículo propio. Lo dejo apuntado para el siguiente.
Aplicado a hardware on-premise genérico
Bajemos a casos concretos.
Caso 1 — RTX 4090 (24 GB, Ada Lovelace)
Configuración típica con Qwen3-8B BF16:
Modelo BF16: ~16 GB
Activations + overhead: ~2 GB
VRAM disponible para KV cache: ~6 GB (con margen)
Con 144 KB/token (Qwen3-8B GQA), eso son ~43 K tokens totales de cache distribuidos entre todas las sesiones simultáneas. En la práctica:
| Concurrencia | Contexto máximo por sesión |
|---|---|
| 1 | 32 768 |
| 4 | 8 192 |
| 8 | 4 096 |
| 16 | 2 048 |
Si necesitas anunciar “soportamos 32 K de contexto” con concurrencia 4+, hay que cuantizar el cache (FP8 baja a 72 KB/token, duplica capacidad) o subir el modelo de gama (un 4B con GQA y cache cuantizado holgaría).
Caso 2 — Cluster 4×H100 (320 GB total, NVLink)
Con tensor parallel = 4 y Llama 3 70B BF16:
Modelo BF16: ~140 GB (35 GB/GPU)
Overhead vLLM por GPU: ~2 GB
VRAM libre para KV por GPU: ~43 GB → ~172 GB agregados
Con 320 KB/token (Llama 3 70B GQA), eso son ~537 K tokens totales de cache. Margen amplio para contextos largos con concurrencia alta:
| Concurrencia | Contexto máximo por sesión |
|---|---|
| 4 | 134 000 |
| 16 | 33 500 |
| 64 | 8 375 |
Para DeepSeek-V3 671 B con MLA: la economía cambia radicalmente porque el cache es ~100× más fino. Lo que limita ya no es el cache sino la VRAM del propio modelo (cuantizado FP8 son ~335 GB → cabe en 4×H100 con margen para KV cache).
Implicaciones operativas
Tres observaciones que repetimos en cada consultoría:
Primero, el contexto máximo anunciado por un modelo no es el que puedes servir en tu hardware. Llama 3 8B “soporta” 128 K, pero en una 4090 con 4 sesiones simultáneas tu contexto efectivo son ~8 K. Es trivial comprobarlo antes de prometérselo al cliente.
Segundo, cuantizar el KV cache es de las optimizaciones con mejor relación coste/beneficio en el contexto ENS. No toca los pesos, no afecta a la reproducibilidad de auditoría, y duplica capacidad. vLLM lo soporta vía --kv-cache-dtype fp8.
Tercero, si los SLA dictan contextos largos con muchos usuarios concurrentes, GQA es necesario pero no suficiente. A medio plazo, hay que mirar modelos con MLA o variantes de attention con compresión.
Lo que no hemos cubierto (próximos artículos)
- PagedAttention y su implementación en vLLM: bloques, tabla de páginas, evicción.
- Prefix caching: cuando varias peticiones comparten el system prompt, no hace falta recomputar las K, V de la parte común.
- Speculative decoding y su interacción con el cache.
- Cache offloading: mover bloques fríos a RAM o a NVMe, técnica clave para contextos > 1 M.
Ver también
- El pipeline LLMOps de seis etapas — el mapa maestro del sistema en producción del que la etapa Deploy es una caja entre seis. Este post entra en una de las decisiones críticas dentro de Deploy.
- PagedAttention por dentro: bloques, tabla de páginas, evicción y el estado del arte del KV cache en 2026 — deep-dive teórico al nivel del bloque y panorama de optimizaciones derivadas (vAttention, EvicPress, RadixAttention, speculative decoding). Continúa este post desde la teoría académica.
- Fine-tuning continuo en producción: del tráfico real al adapter desplegado — cómo se cierra el ciclo entre inferencia y entrenamiento incremental sobre el mismo stack (vLLM + Postgres), con presupuestos de VRAM que incluyen explícitamente el KV cache durante eval.
- Disaggregated serving: prefill y decode en pods especializados — el KV cache deja de ser un buffer privado de la GPU para convertirse en el artefacto que se transfiere entre pods. Aquí la fórmula del tamaño del cache determina la economía de la transferencia.
- El cluster GPU como plataforma multi-tenant — cómo se convierte el cluster en un servicio con tenants, gateway, quotas y aislamiento. Es donde el KV cache deja de ser sólo un recurso de rendimiento y pasa a ser un asunto de plataforma.
- vLLM en Kubernetes: la pieza de inferencia LLM que sí escala — el motor que materializa todo lo que aquí se discute, desplegado en K8s con tensor parallel y autoscaling.
- Quantization para inferencia LLM: FP8, INT4 y GGUF — la cuantización del KV cache (
--kv-cache-dtype=fp8/int4) que aquí se menciona como cuarta técnica ortogonal está desmontada allí con la matemática, los formatos y la pérdida medible. - Speculative decoding: el secretario que adelanta lo que va a decir el jefe — el régimen memory-bound del decode que el KV cache provoca es justo lo que speculative decoding aprovecha: un forward pass con γ tokens cuesta casi lo mismo que con uno solo.
- FlashAttention v1/v2/v3/v4: el bibliotecario que nunca despeja la mesa — el kernel que recorre el KV cache contra Q en cada iteración sin materializar la matriz N×N. Capa de cómputo por debajo del cache.
- MoE inference: el call center con 256 especialistas — la atención sigue siendo dense en todos los MoE de 2026 (Mixtral, DeepSeek, Qwen3, Llama 4, Kimi K2), así que el KV cache mantiene su forma; MLA de DeepSeek es la optimización ortogonal que lo comprime ~10× para hacer viable el contexto largo en clusters modestos.
- Continuous batching — el scheduler iterativo gestiona la asignación dinámica del KV cache entre requests; sin PagedAttention el continuous batching fragmentaría la HBM, y sin continuous batching el KV cache se infrautilizaría con padding.
- Capacity planning para inferencia LLM on-premise — el KV cache es el componente dominante del presupuesto de VRAM cuando se dimensiona un cluster a partir de un SLO; allí se monta la hoja de cálculo paso a paso.
- Optimizando el prefill en vLLM — los cuatro knobs concretos (chunked prefill, prefix caching, FP8 KV, max-model-len) que traducen la teoría del KV cache en parámetros de producción para RTX 4090 y L40.
- Optimizando el decode en vLLM — cómo
--gpu-memory-utilization, speculative decoding y KV cache FP8 se combinan para exprimir el hardware pequeño durante la fase de generación.
Referencias
- Vaswani et al., Attention Is All You Need (NeurIPS 2017) — paper fundacional del transformer.
- Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints (EMNLP 2023).
- Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention (SOSP 2023) — paper original de vLLM.
- DeepSeek-AI, DeepSeek-V2 Technical Report (2024) — introducción de Multi-Head Latent Attention.
- Documentación oficial de vLLM: https://docs.vllm.ai/.
- Llama 3 model card (Meta): especificaciones GQA, n_layers, n_kv_heads.