La mayoría de los errores de dimensionamiento de GPU para la inferencia de grandes modelos de lenguaje ocurren antes de pedir cualquier hardware. Un equipo elige un modelo, encuentra una GPU con memoria suficiente para cargarlo y da el trabajo por terminado.
Cargar el modelo es solo la primera restricción. La capacidad de inferencia depende de tres factores a la vez: la memoria para los pesos, la memoria para la caché de atención de cada solicitud activa y la velocidad a la que la GPU puede generar tokens dentro del objetivo de latencia que usted prometió.
Empiece por la carga de trabajo, no por la GPU
Antes de comparar aceleradores, deje por escrito lo que el servicio tiene que hacer.
- Modelo y precisión. Número de parámetros, arquitectura (capas, cabezas de atención, cabezas de clave/valor, dimensión de cabeza) y la precisión con la que está dispuesto a servirlo.
- Longitudes de contexto. El número típico y el percentil 95 de tokens de entrada por solicitud, además de la longitud de salida típica y máxima.
- Forma del tráfico. Solicitudes por segundo en la hora de mayor actividad, no el promedio diario, y qué tan pronunciados son los picos.
- Objetivos de latencia. Tiempo hasta el primer token (cuánto tarda el usuario en ver algo) y tiempo por token de salida (con qué rapidez fluye el texto a partir de ahí).
- Aislamiento y ubicación. Si los prompts y las salidas pueden salir de un entorno o un país determinado, lo que puede descartar la capacidad compartida sea cual sea el precio.
Un chat interactivo, una búsqueda aumentada por recuperación, el resumen de documentos y el scoring por lotes fuera de línea pueden ejecutar el mismo modelo con huellas de hardware completamente diferentes. Un trabajo de resumen con 8.000 tokens de entrada y una respuesta de 200 tokens exige partes del sistema distintas de las que exige un asistente de chat con 1.000 tokens de entrada y 600 de salida.
Memoria, primera parte: los pesos del modelo
Multiplique el número de parámetros por los bytes por parámetro de la precisión con la que sirve el modelo. Las reglas prácticas habituales son 2 bytes por parámetro en FP16 o BF16, 1 byte en INT8 o FP8 y unos 0.5 bytes en formatos de 4 bits, más una pequeña cantidad para las escalas de cuantización.
- 8B parámetros. Unos 16 GB en FP16, 8 GB en INT8 y de 4 a 5 GB en INT4.
- 70B parámetros. Unos 140 GB en FP16, 70 GB en INT8 y de 35 a 40 GB en INT4.
- Parámetros de la clase 400B. Unos 800 GB en FP16, 400 GB en INT8 y de 200 a 230 GB en INT4, lo que implica un nodo con varias GPU incluso con cuantización.
El contexto de CUDA, los búferes de activaciones, los búferes de comunicación para el paralelismo de tensores y la fragmentación suelen ocupar varios gigabytes por GPU. Los motores de servicio como vLLM permiten definir la fracción de memoria de la GPU que pueden reservar; un valor de planificación de entre el 85 y el 90 por ciento de la memoria física como memoria utilizable es un punto de partida razonable.
Los pesos de 8 bits se sirven ampliamente con una pérdida medible pequeña en la mayoría de las tareas. Los pesos de 4 bits reducen la memoria a la mitad otra vez, pero pueden degradar de forma más notable el razonamiento, el código y la salida multilingüe, así que evalúelos con sus propios prompts antes de planificar la capacidad en función de ellos.
Memoria, segunda parte: la KV cache determina la concurrencia
Durante la generación, cada solicitud conserva las claves y los valores de atención de cada token que ha visto. Este KV cache crece con la longitud del contexto y con el número de solicitudes concurrentes, y en un servidor con mucha actividad suele ocupar más memoria que los propios pesos.
El tamaño por token es: 2 (una clave y un valor) multiplicado por el número de capas, por el número de cabezas key/value, por la dimensión de cabeza y por los bytes por elemento. Para un modelo típico de la clase 70B con grouped-query attention (80 capas, 8 cabezas key/value, dimensión de cabeza 128) en FP16, eso da 2 x 80 x 8 x 128 x 2 bytes, unos 320 KB por token.
A 320 KB por token, una solicitud con 4.000 tokens de contexto usa alrededor de 1.3 GB. Cincuenta solicitudes así necesitan unos 65 GB, casi el tamaño de los propios pesos INT8.
- Asignación paginada. Los motores que asignan la caché en bloques pequeños (paged attention) solo reservan memoria para los tokens que existen, de modo que puede planificar según el contexto promedio, no el máximo, con un margen para las solicitudes largas.
- Cuantización de la caché. Almacenar el KV cache en FP8 reduce su huella aproximadamente a la mitad y duplica el número de secuencias que caben, normalmente con un costo de calidad moderado que conviene probar.
- Caché de prefijos. Cuando muchas solicitudes comparten un prompt de sistema o un documento largos, reutilizar sus claves y valores en caché ahorra tanto memoria como cómputo de prefill.
- Límites de contexto. Limitar el contexto máximo por solicitud suele ser la palanca de capacidad más barata disponible, porque un puñado de solicitudes muy largas puede dejar sin recursos a todas las demás.
Throughput, latencia y procesamiento por lotes
La inferencia tiene dos fases con cuellos de botella distintos. El prefill procesa todo el prompt de una vez y está limitado por el cómputo; una aproximación útil es de 2 operaciones de punto flotante por parámetro y por token, de modo que un modelo de 70B necesita unos 140 GFLOP por cada token de entrada. Después, el decode genera un token a la vez por solicitud y está limitado por el ancho de banda de memoria, porque cada paso lee los pesos y la KV cache de la solicitud desde la memoria de la GPU.
Eso da un límite sencillo para la velocidad de un solo flujo: el ancho de banda de memoria dividido entre los bytes leídos por token. Un modelo con 70 GB de pesos INT8 repartidos entre dos GPU con unos 2 TB/s cada una puede leer los pesos completos como máximo unas 57 veces por segundo, por lo que una solicitud no puede generar más de unos 57 tokens por segundo en esa configuración, y en la práctica la cifra será menor.
El batching es lo que hace rentable la inferencia. El batching continuo, hoy estándar en motores como vLLM y en stacks basados en Triton, incorpora nuevas solicitudes al lote en ejecución en cada paso, en lugar de esperar a que termine un lote. El throughput agregado crece con fuerza a medida que aumenta el tamaño del lote, hasta que el KV cache se llena o el cómputo pasa a ser el límite.
El costo del procesamiento por lotes es la latencia. La planificación de capacidad es por tanto un equilibrio: elija el lote más grande que siga cumpliendo sus objetivos de tiempo hasta el primer token y de tiempo por token de salida en el percentil 95, y dimensione la flota a partir del throughput que mida en ese punto, no del throughput máximo de un gráfico de benchmark.
Cómo estimar la concurrencia a partir del tráfico
La concurrencia, es decir, el número de solicitudes en curso al mismo tiempo, es lo que consume KV cache y plazas en el lote. Puede estimarse con la ley de Little: la concurrencia promedio es igual a la tasa de llegada multiplicada por el tiempo promedio que cada solicitud pasa en el sistema.
Si el tráfico pico es de 5 solicitudes por segundo y cada solicitud tarda 14 segundos desde su llegada hasta el último token (alrededor de 1 segundo de cola y prefill más 400 tokens de salida a 30 tokens por segundo), el sistema mantiene unas 70 solicitudes simultáneas. Multiplique esa cifra por el promedio de tokens retenidos por solicitud y por el tamaño de KV por token, y obtendrá la memoria de caché que requiere el pico.
- Use el pico, no el promedio. El tráfico interactivo suele alcanzar de dos a cuatro veces su promedio diario durante la hora de mayor actividad.
- Vigile la longitud de salida. La concurrencia crece con el tiempo que las solicitudes permanecen abiertas, y los tokens de salida son la parte lenta, así que duplicar la longitud media de salida duplica aproximadamente la concurrencia.
- Tenga en cuenta los reintentos y los agentes. Los agentes que invocan herramientas y los reintentos automáticos pueden emitir varias llamadas al modelo por cada acción del usuario, lo que multiplica la tasa de llegada efectiva.
Un ejemplo práctico
Considere un asistente interno basado en un modelo de la clase 70B con grouped-query attention, servido con pesos en INT8 y KV cache en FP16. La carga pico es de 5 solicitudes por segundo. Las solicitudes promedian 2.000 tokens de entrada y 400 de salida. Los objetivos son menos de 1,5 segundos hasta el primer token y al menos 25 tokens por segundo de streaming en el percentil 95. El hardware candidato son GPU de 80 GB con unos 2 TB/s de ancho de banda de memoria cada una.
- Pesos. 70B parámetros a 1 byte cada uno son unos 70 GB. Una GPU de 80 GB no puede alojar eso más una caché útil, así que la unidad mínima son dos GPU con paralelismo de tensores: 160 GB físicos, unos 144 GB utilizables al 90 por ciento.
- Presupuesto de caché. 144 GB menos 70 GB de pesos dejan unos 74 GB para el KV cache.
- Demanda de caché. Según la ley de Little, unas 70 solicitudes concurrentes. Cada una ocupa unos 2.400 tokens al final, aproximadamente 0,8 GB a 320 KB por token, así que la demanda pico ronda los 55 GB. Cabe, con un margen de alrededor del 25 por ciento.
- Velocidad de decodificación. Cada paso lee unos 35 GB de pesos por GPU más la parte de la caché que corresponde a esa GPU, unos 27 GB en el pico. A 2 TB/s, eso supone aproximadamente 31 ms por paso antes de la sobrecarga, es decir, unos 30 tokens por segundo por flujo y unos 2.000 tokens de salida por segundo en total. Son exactamente los 2.000 tokens por segundo que exige el pico, sin ningún margen.
- Carga de prefill. 5 solicitudes x 2.000 tokens son 10.000 tokens de entrada por segundo, alrededor de 1,4 PFLOP/s de trabajo. Esto compite con la decodificación por las mismas GPU y hará que el streaming caiga por debajo del objetivo durante las ráfagas.
La conclusión es que una réplica de dos GPU aloja el modelo y la caché, pero no tiene margen de throughput en el pico ni redundancia. Dos réplicas, cuatro GPU en total detrás de un balanceador de carga, reducen aproximadamente a la mitad la carga por réplica, mantienen la latencia dentro del objetivo durante las ráfagas y permiten retirar una réplica para mantenimiento en las horas más tranquilas.
Utilización, escalado horizontal y costo por millón de tokens
Los porcentajes de utilización de GPU que reportan las herramientas de monitoreo pueden inducir a error, porque una GPU ocupada leyendo memoria para un lote de una sola solicitud aparece como totalmente utilizada mientras hace poco trabajo útil. En su lugar, siga las métricas que se corresponden con la capacidad: tokens por segundo generados, ocupación del KV cache, solicitudes en espera en cola y percentiles de latencia del tiempo hasta el primer token y del tiempo por token de salida.
- Escale horizontalmente cuando se formen colas. Colas sostenidas en el pico, o una ocupación del KV cache por encima del 90 por ciento con solicitudes desalojadas, significan que la réplica está llena.
- Escale horizontalmente cuando la latencia se desvíe. Si el percentil 95 del tiempo por token de salida se acerca poco a poco al objetivo mientras el throughput se mantiene plano, el lote es demasiado grande para la réplica.
- Escale verticalmente cuando el modelo no quepa. Más memoria por GPU o más GPU por réplica ayudan cuando los pesos y la caché mínima no caben, o cuando predominan los contextos largos.
- Mantenga N+1. Un servicio importante debería sobrevivir a la pérdida de una réplica en el pico, lo que suele determinar el número de réplicas más que el throughput bruto.
El costo por millón de tokens se deriva directamente de estas cifras: divida el costo horario de la flota entre los millones de tokens que produce por hora. Con un precio puramente hipotético de US$ 2,50 por GPU-hora, el ejemplo de cuatro GPU cuesta US$ 10 por hora. A la salida pico completa de 2.000 tokens por segundo, produce 7,2 millones de tokens de salida por hora, unos US$ 1,40 por millón. Si la carga promedio a lo largo del día es el 30 por ciento del pico, la misma flota produce unos 2,2 millones de tokens por hora y el costo efectivo sube a unos US$ 4,60 por millón.
La utilización influye en el costo unitario más que la tarifa por hora. Las cargas de trabajo que se pueden aplazar, como el resumen por lotes, el recálculo de embeddings o las ejecuciones de evaluación, pueden ocupar las horas ociosas de la capacidad interactiva y reducir el costo combinado.
Lista de verificación de planificación de capacidad
- Registre parámetros, capas, cabezas key/value y dimensión de cabeza.
- Defina la precisión de los pesos y el KV cache. Pruebe la calidad con sus propios prompts.
- Calcule la memoria de los pesos y el mínimo de GPU por réplica. Reserve del 10 al 15 por ciento para sobrecarga.
- Calcule bytes de KV cache por token y el presupuesto tras los pesos.
- Mida o estime el RPS pico y el promedio de tokens de entrada y salida.
- Use la ley de Little para estimar la concurrencia pico y la caché necesaria.
- Defina objetivos p95 para el tiempo hasta el primer token y el tiempo por token de salida.
- Haga benchmarks del motor con la concurrencia objetivo. Registre los tokens/s sostenidos por réplica.
- Dimensione réplicas por throughput pico con margen, más una para N+1.
- Limite el contexto y la salida por solicitud. Use caché de prefijos en prompts repetidos.
- Escale según la profundidad de cola, el uso de la caché y la latencia, no solo la GPU.
- Calcule el costo por millón de tokens en el pico y con carga media. Lotes en horas inactivas.
- Confirme dónde pueden residir prompts, salidas y pesos, y luego elija la ubicación.
Cómo puede ayudar Vonahost
Vonahost cotiza la capacidad de GPU por proyecto, con el modelo de GPU, la cantidad y el plazo de entrega confirmados por escrito, y admite despliegues privados en los que los datos y los modelos permanecen en el entorno del cliente. Los despliegues usan herramientas estándar como PyTorch, vLLM, Triton y Kubernetes, por lo que el método de dimensionamiento anterior se traslada directamente a un benchmark en el hardware propuesto.
Cada propuesta de Vonahost indica la configuración, la ubicación, las responsabilidades y el precio mensual en dólares estadounidenses, y los clientes eligen el país donde se ejecuta cada servidor.