Prefill vs decodificación: cómo se ejecuta la generación
Pulsa Enter y la generación corre en dos fases con físicas completamente distintas. El prefill procesa todo tu prompt en una pasada paralela — intensivo en cómputo, rápido por token, pero esperas todo ello antes de que aparezca la primera palabra. La decodificación luego emite la respuesta un token a la vez — cada paso relee esencialmente todos los pesos del modelo desde memoria para producir un token. «El primer token lento, luego fluye» no es una peculiaridad de tu instalación; son estas dos fases.
Fase 1: prefill — el prompt
- Todos los tokens del prompt pasan por el modelo simultáneamente: grandes multiplicaciones de matrices en paralelo, exactamente aquello para lo que están hechas las GPU. La utilización es alta; los tokens por segundo son altos.
- Lo sientes como tiempo-hasta-el-primer-token (TTFT): el silencio tras pulsar Enter.
- La pasada también llena la caché KV con los vectores clave/valor de cada token del prompt — el borrador que leerá la decodificación.
- Prompts más largos, TTFT linealmente más largo: los prompts de sistema grandes, los documentos de RAG y el historial de chat hacen prefill cada vez, salvo que tu motor cachee prefijos.
Fase 2: decodificación — la respuesta
- Un token por pasada hacia adelante. Esa pasada necesita todos los pesos; producir un solo token significa transmitir el modelo entero desde la VRAM.
- El techo es el ancho de banda de memoria, no el cómputo: aproximadamente tok/s de decodificación ≈ ancho de banda efectivo ÷ bytes de pesos. 8 GB de pesos en una tarjeta con ~400 GB/s efectivos ≈ techo de 50 tok/s.
- Por eso la cuantización acelera la decodificación: menos bits por peso significan menos bytes que transmitir en cada paso (véase velocidad).
Por qué la asimetría: el prefill procesa miles de tokens por lectura de pesos (matrices enormes, intensidad aritmética alta — limitado por cómputo), la decodificación procesa exactamente uno (cada byte de pesos se recupera para un solo token — limitado por ancho de banda). Mismos pesos, cuellos de botella opuestos.
total_time ≈ prompt_tokens / prefill_tok_s + output_tokens / decode_tok_s
Ejemplo resuelto
prompt: 1,000 tokens prefill 2,000 tok/s → 0.5 s (TTFT)
salida: 300 tokens decode 40 tok/s → 7.5 s
total ≈ 8.0 s — el 94% del tiempo de reloj es decodificación
- El primer medio segundo procesó 1,000 tokens; los siguientes 7.5 segundos producen 300. Mismo modelo, misma GPU, diferencia de 50× — fase distinta, no esfuerzo distinto.
- 40 tok/s son aproximadamente 160 caracteres de inglés por segundo (≈4 caracteres/token): más rápido de lo que nadie teclea, por eso la lectura en flujo es cómoda (tokens).
- Los mismos 40 tok/s en coreano son aproximadamente 40–60 caracteres/s: tasa de tokens idéntica, menos texto por token.
- La longitud de salida es una palanca del lado de la decodificación: max_tokens limita cuánto corre la generación, las secuencias de parada la terminan antes. Ambas cambian el tiempo de reloj linealmente (parámetros del motor).
- El streaming cambia la percepción, no la física: ves ocurrir la decodificación en vez de esperarla, a los mismos 40 tok/s.
Ejemplo resuelto 2: el caso RAG
prompt: 12,000 tokens (sistema + 20 fragmentos recuperados) prefill 1,500 tok/s → 8.0 s
salida: 500 tokens decode 40 tok/s → 12.5 s
total ≈ 20.5 s — el TTFT por sí solo es el 39% de la espera
Esta es la forma de las configuraciones locales cargadas de recuperación: prompts gordos significan que el modelo «piensa» durante segundos antes de teclear. Remedios, en orden de palanca:
- Recupera menos — 3–5 fragmentos suelen vencer a 20 (RAG).
- Mantén estable el prompt de sistema para que el motor pueda reutilizar un prefijo cacheado.
- Recorta el historial: los turnos viejos se pueden resumir en vez de reproducirlos completos.
La caché KV: el borrador que crece
Sin caché, generar el token N recomputaría la atención sobre todos los N−1 tokens anteriores desde cero — cada paso repitiendo trabajo idéntico, coste total cuadrático en longitud. En su lugar:
- El prefill calcula claves y valores para todos los tokens del prompt y los almacena una vez.
- Cada paso de decodificación calcula solo la consulta/clave/valor del token nuevo y añade su K/V a la caché.
- La atención para el token nuevo es su consulta multiplicada en punto contra todas las claves almacenadas.
- Un token decodificado, en orden: incrustarlo, correr las capas leyendo la caché, proyectar al vocabulario, muestrear — añadir su K/V, repetir.
Ahora cada paso de decodificación es lineal en la longitud del contexto (leer la caché) en vez de cuadrático (recomputarlo todo). El precio es la propia caché, que crece con cada token:
bytes KV ≈ 2 × capas × kv_heads × head_dim × bytes_por_valor × contexto
modelo clase 8B (32 capas, 8 cabezas KV, dim de cabeza 128, FP16):
2 × 32 × 8 × 128 × 2 B ≈ 128 KiB por token
→ ~2.6 GB con contexto de 20k, ~17 GB con contexto de 128k
Esa caché compite con los pesos por la VRAM — los chats de contexto largo tumban cajas que corren el mismo modelo sin problema con prompts cortos (caché KV, cálculo de VRAM).
El procesamiento por lotes cambia la economía
Leer 8 GB de pesos para emitir un token es un despilfarro; la misma lectura puede servir a muchas secuencias a la vez. Agrupa 8 peticiones en lote y una transmisión de pesos produce 8 tokens — el rendimiento sube casi linealmente hasta saturar el cómputo. Este es todo el truco detrás del servicio (APIs de servicio, concurrencia). Solo en un portátil pagas el flete completo por token; los servidores lo amortizan entre usuarios simultáneos.
Leer los medidores
| Medidor | Fase | Principal motor |
|---|---|---|
| TTFT | prefill | longitud del prompt, cómputo, aciertos de caché de prefijo |
| Prompt eval tok/s | prefill | cómputo, tamaño de lote |
| Generation tok/s | decodificación | ancho de banda de memoria, bytes de pesos, lote |
| Rendimiento (req/s) | ambos | tamaño de lote, reutilización de caché de prefijo, huecos paralelos |
| Memoria de contexto | ambos | bytes KV por token, cuantización de la caché |
Mide antes de afinar: todo motor serio registra velocidades de evaluación de prompt y de generación por petición. Un minuto de registros te dice qué fase se come tu latencia; adivinar no.
Ajustar sigue a la fase: prompts más cortos y caché de prefijos arreglan el TTFT; la cuantización y pesos más pequeños arreglan la decodificación (parámetros del motor, resolución de problemas).
Relacionados: velocidad · caché KV · concurrencia · tokens