Capítulo 18 · Inferencia · 8 min
Por qué el 2.º token es más rápido que el 1.º
El KV cache y la generación autorregresiva. Prefill vs decode, TTFT, y por qué el cache lo cambia todo.
La ilusion del tiempo de respuesta
Le haces una pregunta a ChatGPT. Tarda alrededor de un segundo en empezar a responder. Despues las palabras salen casi al instante, mas rapido de lo que puedes leerlas.
Esta asimetria no es un capricho de interfaz. Es la huella de una optimizacion fundamental, sin la cual generar texto con un LLM costaria cien veces mas: el KV cache.
Como un Transformer genera un token
En cada paso de generacion, el Transformer debe producir un nuevo token. Para ello, calcula la atencion del ultimo token sobre todos los tokens anteriores. Eso es lo que le permite tener en cuenta el contexto entero.
Pero la atencion necesita, para cada token del contexto, dos vectores: una clave (K) y un valor (V). Sin optimizacion, en cada nuevo token generado, el modelo recalcula K y V para toda la secuencia — incluidos los tokens ya procesados en el paso anterior. Es un trabajo O(n²) sobre la longitud de la secuencia: doblar el numero de tokens cuadruplica el coste.
Es trabajo desperdiciado: esos vectores no han cambiado. El token nº3 tiene la misma clave K₃ que tenia en el paso anterior.
El KV cache: nunca recalcular lo que ya tienes
La idea es trivial y decisiva. Se mantienen en memoria (en el GPU) las K y V de todos los tokens ya procesados. En cada nuevo paso de generacion, se calcula solo la K y la V del nuevo token, que se añade al cache.
La atencion entonces lee el cache completo, pero el calculo a hacer en este paso es O(1) en tamaño — no O(n).
Sin caché, cada nuevo token recalcula toda la attention sobre el prefijo — coste en O(n²). Con caché, solo se calcula la nueva línea. Eso es lo que separa el primer token (lento, prefill) del segundo (rápido, decode).
A la izquierda, sin cache: cada paso vuelve a dibujar todas las lineas. A la derecha, con cache: solo se añade una linea. Tras unos pocos tokens, la diferencia en operaciones acumuladas se vuelve enorme.
Prefill vs decode: dos fases bien distintas
La generacion con un LLM se divide en dos fases que los ingenieros de inferencia distinguen cuidadosamente.
Prefill. El modelo recibe el prompt completo y calcula K y V para todos sus tokens en paralelo. Es rapido en terminos de throughput — el GPU esta saturado — pero tarda si el prompt es largo. Eso es lo que determina el TTFT (Time To First Token), el retraso antes de que aparezca la primera palabra.
Decode. El modelo genera el resto, un token a la vez, reutilizando el cache. Cada paso es rapido individualmente, pero secuencial: no se pueden paralelizar los tokens futuros, porque cada uno depende del anterior. Eso es lo que determina el ITL (Inter-Token Latency).
Las dos fases tienen perfiles completamente distintos:
| Prefill | Decode | |
|---|---|---|
| Paralelizable? | Si (todos los tokens a la vez) | No (secuencial) |
| Cuello de botella hardware | Computo (FLOPs) | Memoria (lectura del cache) |
| Efecto de la longitud | Lineal en N | Lineal en N por token |
| Metrica clave | TTFT | ITL |
En un prompt largo, el prefill puede tardar varios segundos. En una salida larga, el decode domina — y esta limitado por la velocidad a la que se puede leer el KV cache desde la memoria HBM del GPU.
Por que los providers facturan los input tokens de forma distinta
Si miras los precios de OpenAI, Anthropic o Google, los input tokens son sistematicamente mas baratos que los output tokens — a menudo 4× o 5× menos. No es arbitrario. El prefill, que procesa los input tokens, es masivamente paralelo y usa el GPU eficientemente. El decode genera los output tokens uno a uno y aprovecha mal el hardware.
Mas sutilmente: Anthropic, OpenAI y otros ofrecen ahora prefix caching. Si varias peticiones empiezan con el mismo system prompt, el KV cache de ese prefijo se calcula una sola vez y se reutiliza. Eso es lo que hace que los agentes y los chatbots multi-turno sean economicamente viables: sin prefix caching, cada turno costaria reprocesar la conversacion entera.
El coste oculto: la memoria GPU
El KV cache no es gratis en memoria. Ocupa:
memoria = 2 × n_layers × n_heads × d_head × seq_len × batch_size × 2 bytes (FP16)
Para un modelo de 70 mil millones de parametros con un contexto de 128.000 tokens y batch de 1, hablamos de decenas de gigabytes. Esto es a menudo lo que limita la longitud de contexto practicable, mas que la capacidad del modelo en si para razonar sobre la secuencia.
Para empujar mas alla, existen varias tecnicas:
- Cache quantization: almacenar K y V en INT8 o INT4 en vez de FP16, dividiendo la memoria entre 2 o 4.
- MQA / GQA (Multi-Query / Grouped-Query Attention): compartir las K/V entre varias heads. Llama 2 70B y Llama 3 usan GQA, lo que reduce drasticamente el tamaño del cache.
- Sliding window attention: mantener solo una ventana reciente del cache (Mistral, Gemma).
- PagedAttention (vLLM): tratar el cache como paginas de memoria virtual, para gestionar mejor el batching dinamico.
Quantization, en dos palabras
La palabra aparece por todas partes en esta parte: QLoRA en 4 bits (capitulo 14), cache quantization justo arriba, modelos GGUF que descargas de Hugging Face. Es el momento de explicar lo que significa.
Quantizar es representar cada parametro del modelo con menos bits. Un numero en coma flotante de 32 bits (FP32) ocupa 4 bytes. En FP16, 2 bytes. En INT8, 1 byte. En INT4, medio byte — la memoria que ocupan los pesos se divide entre 8 respecto al FP32 original.
| Precision | Bytes / parametro | Modelo 70B ocupa |
|---|---|---|
| FP32 | 4 | 280 GB |
| FP16 / BF16 | 2 | 140 GB |
| INT8 | 1 | 70 GB |
| INT4 | 0,5 | 35 GB |
| INT2 (extremo) | 0,25 | 17,5 GB |
El truco: un peso 0,237 no se vuelve exactamente 0,237 en INT4 (que solo tiene 16 valores posibles), sino su valor mas cercano en una rejilla discreta. La perdida de calidad depende del modelo y del metodo, pero suele ser pequeña hasta INT8, modesta en INT4 (un par de % de degradacion en los benchmarks), significativa por debajo.
Las tecnicas modernas (GPTQ, AWQ, GGUF) no cuantizan todos los pesos por igual — preservan la precision en las capas sensibles y comprimen mas agresivamente las demas. Y la quantization del KV cache, mencionada arriba, aplica exactamente la misma idea a las activaciones almacenadas en memoria durante la generacion.
Es esta tecnica la que permite hacer correr Llama 70B en un MacBook con 64 GB de RAM, alli donde la version FP16 pide un cluster.
La leccion
Sin el KV cache, los LLMs en produccion serian impracticables. Una conversacion larga, un agente que razona, un chatbot que recuerda lo que dijiste cinco mensajes atras — nada de eso seria viable economicamente.
Pero ese cache es tambien lo que limita la longitud de contexto. Cuando hablamos de "ventana de 1 millon de tokens", es en gran parte un problema de memoria de cache, no un problema de calculo de atencion.
El KV cache no es una optimizacion mas entre otras. Es lo que transforma la atencion de un mecanismo teorico en una infraestructura de produccion.
Actualizado el