Si usas modelos de lenguaje de gran tamaño (LLM) o desarrollas a partir de ellos, quizás el concepto más importante que debes comprender sea cómo funcionan la inferencia y la memoria caché de clave-valor (KV). Esto se debe a que, independientemente de si trabajas con agentes de programación, generación aumentada por recuperación (RAG) o perfeccionamiento, la inferencia es lo que sucede cada vez que realizas una solicitud a un modelo y obtienes una respuesta (y, por lo tanto, adónde va todo el dinero).

Mientras que el entrenamiento se realiza una sola vez, la inferencia ocurre cada vez que un usuario envía una petición. Por lo tanto, veamos cómo funciona, qué es la memoria caché de KV y las optimizaciones que la mayoría de los equipos usa para ahorrar en costos de infraestructura y reducir la latencia.

La inferencia es un stack, no un archivo de modelo

Alt text: Diagram illustrating the 3 core components needed for model serving: Model weights containing learned parameters, an inference server managing incoming requests, and the underlying hardware accelerator GPU.

Figura 1: Para servir un modelo, se necesitan 3 elementos que trabajen en conjunto: los pesos, un servidor de inferencia y el hardware subyacente.

Un modelo alojado en tu equipo (o HuggingFace) todavía no presta servicio a nadie. Para que la inferencia sea posible, necesitas 3 elementos que funcionen en conjunto:

  • Pesos del modelo: Los archivos con los miles de millones de parámetros aprendidos: Kimi, GLM, Qwen o el que hayas elegido.
  • Servidor de inferencia: Software como vLLM, que carga el modelo, gestiona las solicitudes entrantes y se encarga de las optimizaciones que abordaremos a continuación.
  • Acelerador de hardware: Por lo general, una GPU, que se encarga del trabajo numérico pesado.

Puedes omitir la capa intermedia y ejecutar un modelo directamente en una GPU con PyTorch. Eso funciona bien para un notebook o un solo usuario. Sin embargo, en el momento en que necesitas atender a muchas personas a la vez, el servidor de inferencia es lo que permite usar la GPU a escala de producción (piensa en abrir un archivo HTML localmente frente a servirlo mediante el servidor HTTP Apache).

Los modelos generan un token a la vez

Alt text: Diagram showing autoregressive generation, where each forward pass produces exactly 1 new token that is appended to the context and fed back into the model to predict the next token.

Figura 2: Cada propagación hacia adelante produce exactamente 1 token nuevo, que luego se vuelve a introducir para generar el siguiente.

Los LLM no generan respuestas largas de una sola vez, sino que producen 1 token a la vez, y cada nuevo token depende de todos los anteriores (incluidos los que el propio modelo acaba de generar).

Por lo tanto, si comenzamos con una petición de ejemplo: "The quick brown"

  • El modelo predice "fox" → se añade
  • "The quick brown fox" → predice "jumps" → se añade
  • Y así sucesivamente, hasta que el modelo emite un token especial de fin de secuencia.

Eso es la generación autorregresiva, y lo que la gente subestima es que cada token de una respuesta requiere una propagación completa por el modelo. Una respuesta de 500 tokens significa que el modelo se ejecuta 500 veces, y aquí puedes ver cómo la demanda computacional puede empezar a crecer.

Por qué existe la memoria caché de KV

Alt text: Diagram demonstrating a transformer layer self-attention block, showing a current token's query vector comparing against the key and value vectors of all preceding tokens in the context.

Figura 3 Cada token pasa por el bloque de atención de cada capa y compara su consulta con las claves y los valores de todo lo que tiene antes.

Dentro de cada una de esas propagaciones, los tokens se convierten en embeddings (una representación numérica) para fluir a través de un stack de capas de transformadores, y cada capa tiene un bloque de autoatención donde los tokens se observan entre sí. Ahí es donde comienza el problema de la memoria.

Attention calcula 3 vectores por token:

  • Q, la consulta: Lo que este token quiere saber del contexto
  • K, la clave: El tipo de información que contiene
  • V, el valor: Su contenido real

Para generar el siguiente token, comparas su consulta con la clave de cada token procesado hasta el momento y calculas una suma ponderada de los valores.

¡Pero! Esto es lo verdaderamente importante: La consulta solo se necesita para el token actual. Las claves y los valores se necesitan para todo el historial, pero no cambian. La clave y el valor del token 4 son los mismos en el paso 5 que en el paso 4.

Alt text: Diagram depicting KV cache optimization, showing how key and value vectors for earlier tokens are saved in GPU memory to be reused on subsequent steps rather than recomputed.

Figura 4 Dado que las claves y los valores de los tokens anteriores nunca cambian, se guardan una vez y se reutilizan en lugar de volver a calcularse en cada paso.

Por lo tanto, en lugar de volver a calcularlos en cada paso, los guardamos en la memoria de la GPU y solo calculamos K y V para el nuevo token. Esa es la memoria caché de KV, y ocurre en cada una de las N capas del modelo, por lo que el ahorro se multiplica por N.

¿Cuánto puede llegar a crecer la memoria caché de KV?

Cada token necesita que sus claves y valores se almacenen en cada capa, con varios conjuntos paralelos por capa (los cabezales de KV). La fórmula es:

2 × num_layers × num_kv_heads × head_dim × dtype_bytes

Tomemos como ejemplo gpt-oss-120b: 36 capas, 8 cabezales de KV, una dimensión de cabezal de 64, 2 bytes por valor. Esto equivale a unos 72 KB por token, pero gpt-oss solo conserva el historial completo en la mitad de sus capas, por lo que la cantidad que realmente aumenta se acerca a los 36 KB por token.

  • 2000 (un turno de chat típico): ~75 MB
  • 8000 (nivel de producción estándar): ~300 MB
  • 32000 (un documento largo o una base de código): ~1,2 GB
  • 128000 (el máximo de gpt-oss): ~4,8 GB

Y ese es un modelo diseñado para ser eficiente a la hora de servirlo. Un modelo denso de 70B con 80 capas y una dimensión de cabezal de 128 (como Llama 3.3 70B) requiere cerca de 320 KB por token, es decir, 9 veces más para la misma conversación. Por eso, las decisiones sobre la arquitectura del modelo son muy importantes para controlar tus costos de inteligencia artificial.

Adónde se destina tu presupuesto de GPU

Un modelo como gpt-oss-120b cabe en una sola GPU NVIDIA H100 de 80 GB. Eso fue todo un hito cuando se lanzó el modelo, pero tras cargar los pesos en la tarjeta, solo te quedan entre 15 y 20 GB de margen para la memoria caché de KV y la sobrecarga de inferencia. Servir a usuarios reales ahora resulta complicado; por ejemplo:

  • Si tu servidor reserva memoria por solicitud, dimensionada para el contexto máximo que esa solicitud podría alcanzar (que es lo que hacían los enfoques anteriores), cada solicitud cuesta 4,8 GB, se use o no. Eso representa solo 3 usuarios simultáneos en una H100. ¡Uf!
  • Si en cambio asignas lo que cada solicitud realmente utiliza, una solicitud típica de 8000 cuesta 300 MB. La misma tarjeta, el mismo modelo, 50 o 60 usuarios. Todo esto con el mismo hardware, pero la diferencia radica por completo en cómo se gestiona la memoria de la GPU, motivo por el cual este tema es tan importante.
Alt text: Diagram illustrating memory waste in GPU KV cache allocations caused by pre-allocating memory sized for maximum worst-case context lengths.

Figura 5: Reservar memoria para la longitud de contexto en el peor de los casos deja vacía la mayor parte de la memoria caché de KV.

¿Qué hacen al respecto los servidores de inferencia en producción, como vLLM?

Pues bien, principalmente 3 cosas:

1. PagedAttention

PagedAttention divide la memoria caché de KV en pequeños bloques de tamaño fijo que pueden ubicarse en cualquier lugar de la memoria, con una tabla que realiza un seguimiento de la ubicación de los bloques de cada solicitud. No se reserva nada para contextos que quizás nunca uses. Si has trabajado con memoria virtual en un sistema operativo, esto te resultará familiar: de ahí proviene la idea.

Alt text: Diagram illustrating PagedAttention scattering KV cache blocks into small fixed-size chunks across GPU memory and dynamically tracking them using a lookup table.

Figura 6: PagedAttention distribuye la memoria caché en pequeños bloques de tamaño fijo y les hace seguimiento con una tabla de consulta, por lo que no se reserva nada por adelantado.

2. Procesamiento por lotes continuo

Con el procesamiento por lotes continuo, en lugar de esperar a que finalice un lote completo, las solicitudes terminadas salen y las nuevas entran a medida que se liberan espacios. La GPU se mantiene ocupada continuamente.

Alt text: Comparison diagram showing static batching holding GPU slots until the slowest request finishes versus continuous batching filling freed slots immediately as requests complete.

Figura 7: El procesamiento por lotes estático hace que cada solicitud espere a la más lenta, mientras que el procesamiento por lotes continuo ocupa de inmediato cada espacio liberado.

3. Almacenamiento en caché de prefijos

Cuando las solicitudes comparten un prefijo (una petición del sistema, un documento recuperado o el mismo archivo de repositorio en el contexto de un agente de programación), esto reutiliza las K y V almacenadas en caché en lugar de volver a calcularlas.

Alt text: Diagram demonstrating prefix caching, showing multiple incoming requests reusing pre-computed key and value vectors for shared opening context or system prompts.

Figura 8: Cuando las solicitudes comparten el mismo texto inicial, el trabajo ya realizado para ese prefijo se reutiliza en lugar de recalcularse.

Ninguna de estas técnicas modifica el modelo, pero cambian la eficiencia con la que lo ejecutas.

Luego está la reducción del propio modelo

La cuantificación es un método para almacenar pesos (o activaciones) con menor precisión, de modo que ocupen menos espacio y se procesen más rápido. La mayoría de los modelos se distribuyen en BF16, o 16 bits por parámetro. Cuando pasas a FP8 (coma flotante de 8 bits) o INT8 (entero de 8 bits), reduces a la mitad la cantidad de memoria utilizada sin comprometer la precisión de referencia. Pasa a 4 bits y se reduce a una cuarta parte. Por ejemplo, todos los modelos cuantificados en el repositorio de Hugging Face de Red Hat AI recuperan más del 99 % de su precisión de referencia.

El modelo gpt-oss-120b es un caso muy útil porque el trabajo ya está hecho para ti. Con 117B parámetros en BF16, los pesos serían de unos 234 GB y necesitarías 3 GPU de 80 GB para cargarlos. OpenAI entrenó posteriormente el modelo con cuantificación MXFP4 en los pesos de MoE (Mixture of Experts), lo que reduce su tamaño por debajo de los 80 GB y permite ejecutarlo en una sola tarjeta.

  • BF16 (hipotético): ~234 GB → 3 GPU
  • MXFP4, tal como se distribuye: Cabe en una sola GPU de 80 GB
Diagram contrasting full-precision 16-bit number formats (BF16) with lower-precision formats (FP8, INT8, MXFP4), showing how lower precision yields a significantly smaller memory footprint.

Figura 9: Los formatos numéricos de menor precisión sacrifican rango y detalle a cambio de una huella de memoria mucho menor.

La mayoría de los modelos no vienen así, momento en el que debes hacerlo tú mismo o consultar nuestros modelos comprimidos en HuggingFace. Al final, la cuantificación ofrece 2 grandes ventajas: Los pesos cuantificados implican que se transfieren menos datos desde la memoria de gran ancho de banda (HBM) a la memoria estática de acceso aleatorio (SRAM) en cada propagación hacia adelante, lo cual mejora la latencia. Las activaciones cuantificadas permiten que los núcleos tensoriales hagan los cálculos con menor precisión y procesen más operaciones por segundo, lo cual aumenta el rendimiento. Los esquemas solo de pesos como W8A16 (peso de 8 bits, activación de 16 bits) te ofrecen la primera ventaja, pero formatos como W8A8 (peso Int8, activación Int8) te brindan ambas.

Diagram showing how smaller quantized model weights transfer faster from high-bandwidth memory into GPU SRAM and run at higher operational throughput on tensor cores.

Figura 10: Los pesos más pequeños se transfieren con mayor rapidez a la memoria más rápida de la GPU, y los cálculos de baja precisión se ejecutan con un rendimiento mucho mayor en los núcleos tensoriales.

En la práctica, FP8 reduce a la mitad tus requisitos de memoria y proporciona un rendimiento hasta 1,6 veces superior con un impacto mínimo en la precisión. Y no, no estás volviendo más tonto al modelo. Las técnicas calibradas, como la cuantificación generalizada posterior al entrenamiento (GPTQ), la cuantificación de pesos en función de la activación (AWQ) y SmoothQuant, utilizan un pequeño conjunto de datos representativo para determinar qué pesos son los más importantes y protegerlos, de modo que la pérdida de calidad suele ser inferior a un punto porcentual.

Guía rápida de optimización de modelos de inteligencia artificial

Técnica

Dónde se aplica

Qué obtienes

PagedAttention

Tiempo de ejecución

Más solicitudes simultáneas en la misma memoria

Procesamiento por lotes continuo

Tiempo de ejecución

La GPU se mantiene ocupada entre solicitudes

Almacenamiento en caché de prefijos

Tiempo de ejecución

Omite el recálculo en contextos compartidos

Cuantización

Modelo, antes de la implementación

Menos GPU, carga más rápida, cálculos más veloces

Sparsification

Modelo, antes de la implementación

Omite los pesos menos relevantes

El entrenamiento es un costo único; la inferencia es el recurrente y representa la mayor parte de la factura. Cada token requiere una propagación hacia adelante completa. La memoria caché de KV es lo que crece con la longitud del contexto y los usuarios simultáneos, y gestionarla es la tarea principal de tu servidor de inferencia. En nuestro ejemplo, la diferencia entre una implementación básica y una optimizada en la misma GPU es de aproximadamente 3 usuarios simultáneos frente a 50. Si optimizas bien la inferencia, aprovecharás mucho mejor el hardware que ya tienes.

P. D.: ¡Si te ha gustado esto!

Si quieres ponerlo en práctica tú mismo, creamos un curso gratuito con DeepLearning.AI y Red Hat eminentemente práctico: Cuantifica un modelo Qwen con LLM Compressor y evalúa el balance de precisión, sírvelo con vLLM, realiza pruebas de rendimiento con GuideLLM y evalúalo con lm-eval: Fast & Efficient LLM Inference with vLLM.

Recurso

Get started with AI Inference: Red Hat AI experts explain

Aprende a diseñar sistemas de inferencia de inteligencia artificial más inteligentes y eficientes. Obtén más información sobre la cuantización, la esparsidad y otras técnicas avanzadas, como vLLM, con Red Hat AI.

Sobre el autor

Cedric Clyburn (@cedricclyburn), Senior Developer Advocate at Red Hat, is an enthusiastic software technologist with a background in Kubernetes, DevOps, and container tools. He has experience speaking and organizing conferences including DevNexus, WeAreDevelopers, The Linux Foundation, KCD NYC, and more. Cedric loves all things open-source, and works to make developer's lives easier! Based out of New York.

UI_Icon-Red_Hat-Close-A-Black-RGB

Navegar por canal

automation icon

Automatización

Las últimas novedades en la automatización de la TI para los equipos, la tecnología y los entornos

AI icon

Inteligencia artificial

Descubra las actualizaciones en las plataformas que permiten a los clientes ejecutar cargas de trabajo de inteligecia artificial en cualquier lugar

open hybrid cloud icon

Nube híbrida abierta

Vea como construimos un futuro flexible con la nube híbrida

security icon

Seguridad

Vea las últimas novedades sobre cómo reducimos los riesgos en entornos y tecnologías

edge icon

Edge computing

Conozca las actualizaciones en las plataformas que simplifican las operaciones en el edge

Infrastructure icon

Infraestructura

Vea las últimas novedades sobre la plataforma Linux empresarial líder en el mundo

application development icon

Aplicaciones

Conozca nuestras soluciones para abordar los desafíos más complejos de las aplicaciones

Virtualization icon

Virtualización

El futuro de la virtualización empresarial para tus cargas de trabajo locales o en la nube