Por qué tu LLM autohospedado se atasca con 5 usuarios
Con un usuario funciona, pero cinco se arrastran: batching, límites de la caché KV, prefill y profundidad de cola determinan cuántos atiende tu servidor LLM.
¿Por qué un LLM autohospedado se ralentiza cuando llegan más usuarios?
Un LLM autohospedado se bloquea con 5 usuarios simultáneos porque el servidor todavía genera una respuesta cada vez y los otros cuatro esperan en una cola. La documentación de Ollama es clara sobre el valor predeterminado: OLLAMA_NUM_PARALLEL es «el número máximo de solicitudes paralelas que cada modelo procesa al mismo tiempo; el valor predeterminado es 1». No hay ningún fallo. Cuatro de las cinco personas esperan su turno.
La solución rara vez consiste en usar un equipo más potente. Consiste en utilizar un motor de serving que procese muchas solicitudes en el mismo paso forward del modelo y disponga de memoria libre suficiente para mantener las conversaciones de todos mientras lo hace. Ambas partes son importantes, pero la segunda es la que realmente determina el límite.
Las dos fases por las que pasa cada solicitud
Prefill lee todo el prompt de una vez y construye la caché de atención correspondiente. Todos los tokens del prompt pasan juntos por el modelo, por lo que prefill consiste en una multiplicación de matrices grande y está limitado por el rendimiento aritmético. Decode escribe la respuesta un token cada vez. Para cada token, es necesario volver a leer de la memoria todos los pesos del modelo, mientras que el cálculo realizado sobre ese único token es mínimo. Decode está limitado por el ancho de banda de memoria.
Esta asimetría es la razón principal por la que funciona el procesamiento por lotes. La decodificación para un usuario lee, por ejemplo, 5 GB de pesos por token y deja inactivas la mayoría de las unidades aritméticas. Al añadir una segunda solicitud, el motor lee los mismos 5 GB una sola vez y después calcula dos tokens con ellos. El segundo usuario apenas añade tiempo. Atender las solicitudes estrictamente una detrás de otra desperdicia esa ventaja.
Dos valores describen lo que percibe el usuario. TTFT (time to first token) es la espera en cola más prefill. ITL (inter-token latency) es el intervalo entre los tokens transmitidos y lo determina decode. Un servidor lento suele serlo en uno de estos valores, y las soluciones no son las mismas. Conviene determinar cuál de los dos está limitando el sistema antes de cambiar cualquier ajuste. medir prefill y decode por separado permite averiguarlo.
El batching estático hace que todos esperen a la respuesta más lenta
El batching estático es la versión más simple. Es el resultado de agrupar las solicitudes manualmente en el código de la aplicación. El motor recopila N solicitudes, las ejecuta juntas y mantiene ocupados todos los slots hasta que termina la generación más larga del grupo.
Si un usuario solicita un resumen de 1,200 tokens, cuatro respuestas de una línea permanecen bloqueadas en el batch, porque el batch no libera ningún slot hasta que termina su miembro más lento.
Esto genera dos costes. Las secuencias terminadas siguen ocupando slots sin realizar ningún cálculo útil. Por tanto, el rendimiento efectivo disminuye cuando varía la longitud de salida, y en los chats esta longitud varía mucho. Una solicitud que llega un paso después de formar el batch espera a que se vacíe todo el batch antes de iniciar siquiera el prefill. Por tanto, su TTFT depende del texto de otra solicitud.
El batching continuo admite y retira solicitudes en cada token
El batching continuo planifica cada paso de decodificación por separado. Después de cada paso, el planificador elimina las secuencias que acaban de emitir su token de parada y admite las solicitudes en espera en los slots libres. Una respuesta que termina en el paso 40 libera su slot en el paso 40, no al final de un batch.
Esto no es algo exótico. llama-server documenta -cb, --cont-batching como «si se debe habilitar el batching continuo (también llamado batching dinámico) (valor predeterminado: habilitado)», y vLLM se basa en este concepto. Ollama también sirve solicitudes en paralelo. El valor predeterminado simplemente limita el número a uno. Por eso muchas personas concluyen que su hardware no admite concurrencia, cuando en realidad su configuración la deshabilita.
Los resultados publicados sobre batching continuo suelen medirse en tarjetas de centros de datos que tienen capacidad de cómputo libre y decenas de gigabytes para la caché. La forma de esos resultados se aplica también a su equipo. Su magnitud no, y la sección sobre memoria explica el motivo.
El prefill compite con el decode por los mismos recursos de cómputo
Cuando llega una solicitud nueva mientras se están transmitiendo cuatro respuestas, primero hay que ejecutar el prefill de su prompt, y el prefill consume mucho cómputo. Si el planificador asigna a ese prefill un paso propio, los cuatro usuarios que reciben texto en streaming no obtienen ningún token durante ese paso. Con un prompt largo, esto provoca una pausa visible en todas las ventanas abiertas. Este es el tartamudeo al que se refieren cuando dicen que el servidor se bloquea momentáneamente cada vez que otra persona pulsa enviar.
El prefill segmentado divide un prompt largo en partes y mezcla cada una con el mismo paso en el que se ejecutan los procesos de decode activos. La guía de ajuste de vLLM indica directamente esta compensación: los presupuestos de fragmentos más pequeños «consiguen un ITL mejor porque hay menos operaciones de prefill que ralenticen el decode», mientras que los valores más altos «consiguen un mejor tiempo hasta el primer token (TTFT), porque permiten procesar más tokens de prefill en un lote». Debe decidir qué experiencia proteger: la de la persona que espera a que empiece una respuesta o la de las personas que observan cómo se transmite el texto.
La longitud del prompt determina cuánto afecta este problema. Un prompt de 6,000 tokens con una respuesta de 200 tokens supone 6,000 tokens de trabajo de prefill frente a 200 pasos de decode. Los chats con generación aumentada mediante recuperación y los prompts de sistema largos suelen llevarle a ese escenario. Por tanto, el prefill deja de ser un error de redondeo y se convierte en la operación que mantiene a los usuarios esperando. La caché de prefijos ayuda cuando se repite la parte larga: vLLM expone --enable-prefix-caching, que reutiliza la caché de un prefijo de prompt compartido en lugar de volver a calcularlo para cada solicitud.
La memoria que se agota primero es la caché KV
Cada token de cada conversación activa deja un vector de clave y un vector de valor en cada capa del modelo. Esa es la caché KV (caché de clave/valor), que permite que la fase de decodificación no tenga que volver a calcular todo el prompt para cada token nuevo. Su tamaño por token está fijado por la arquitectura del modelo: 2 (una clave y un valor) por el número de capas, por el número de cabezas de clave/valor, por la dimensión de la cabeza y por los bytes de cada valor. Consulte esos números en config.json del modelo.
Haga el cálculo una vez y el límite deja de ser un misterio. Un modelo 8B típico con 36 capas, 8 cabezas de clave/valor y una dimensión de cabeza de 128, que mantiene la caché en 16 bits, consume 2 36 8 128 2 bytes por token. Eso equivale a 147,456 bytes, aproximadamente 144 KiB. Una conversación de 8,192 tokens necesita, por tanto, unos 1.2 GB de caché. Cinco conversaciones necesitan unos 6 GB, además de los pesos. Esa es la respuesta real a cuántos usuarios caben.
La concurrencia multiplica el contexto, y las herramientas lo indican claramente. La FAQ de Ollama dice: "El procesamiento de solicitudes en paralelo para un modelo determinado aumenta el tamaño del contexto según el número de solicitudes paralelas. Por ejemplo, un contexto de 2K con 4 solicitudes paralelas da como resultado un contexto de 8K y una asignación de memoria adicional." La RAM necesaria escala con OLLAMA_NUM_PARALLEL multiplicado por OLLAMA_CONTEXT_LENGTH. En llama-server, el contexto que se solicita con -c se reparte entre los -np slots. Por tanto, aumentar por sí solo el número de slots reduce lo que puede contener cada solicitud. Consulte el contexto por slot en el registro de inicio en lugar de darlo por supuesto.
vLLM preasigna la memoria. --gpu-memory-utilization (el valor predeterminado es 0.92) es "la fracción de memoria de GPU que usará el ejecutor del modelo". Lo que queda después de cargar los pesos se convierte en el pool paginado de KV. Cuando ese pool se queda sin espacio, el planificador expulsa una solicitud en lugar de provocar un fallo:
WARNING 05-09 00:49:33 scheduler.py:1057] Sequence group 0 is preempted by PreemptionMode.RECOMPUTE mode because there is not enough KV cache space.En el motor V1 de vLLM, el modo de desalojo predeterminado es RECOMPUTE. Por tanto, una solicitud expulsada descarta su caché y vuelve a ejecutar el prefilling cuando se admite de nuevo. Ese trabajo se realiza dos veces. La documentación advierte que "el desalojo y el recálculo pueden afectar negativamente a la latencia de extremo a extremo". Esta línea del registro es la mejor explicación de por qué un usuario tuvo que esperar mucho más que los demás mientras la latencia media parecía normal. Configure disable_log_stats=False para registrar el contador acumulado o lea el contador de desalojos en las métricas de Prometheus que expone vLLM.
Qué cambia con 2, 5 y 20 usuarios simultáneos
Dos usuarios. El cambio es casi imperceptible en una GPU con caché disponible, porque el segundo flujo de decodificación se ejecuta junto al primero con muy poco tiempo adicional. En una VPS que usa sólo CPU y tiene entre 4 y 8 GB de RAM, no es gratis: ambos flujos comparten las mismas vCPU y el mismo ancho de banda de RAM. Por eso, cada usuario obtiene aproximadamente la mitad de tokens por segundo y la demanda de caché se duplica frente a un presupuesto mucho menor.
Cinco usuarios. Aquí los valores predeterminados dejan de ser suficientes y el problema empieza como una cola. Con OLLAMA_NUM_PARALLEL en 1, cuatro personas esperan a quien haya solicitado la respuesta larga, y cada una recupera la velocidad normal cuando llega su turno. Si aumenta el número de procesos paralelos, el problema cambia: cinco ranuras con un contexto de 8K cada una requieren una caché de 40K tokens. Si no cabe en la VRAM, el motor descarga capas a la RAM del sistema. Si tampoco caben en la RAM, el equipo usa swap y los tokens por segundo se desploman.
Veinte usuarios. Veinte personas en una interfaz de chat normalmente no generan veinte solicitudes simultáneas. Es lo más importante que debe entender antes de comprar hardware. Una persona lee una respuesta y tarda entre 20 y 60 segundos en enviar el siguiente mensaje, por lo que la mayor parte de su sesión está inactiva. Veinte agentes o veinte trabajos de resumen de documentos son veinte flujos reales sin tiempo de inactividad. Requieren un equipo diferente. Un desarrollador que haya dirigido un agente de programación a su propio servidor Ollama se acerca más al segundo caso que al primero, porque el agente sigue enviando solicitudes mientras dura la tarea y no deja las pausas de lectura que hace una persona.
¿Sus usuarios generan solicitudes simultáneas o sólo están conectados?
Calcule las solicitudes en curso antes de dimensionar nada. La fórmula es sencilla: solicitudes en curso = usuarios, multiplicados por los segundos empleados en generar cada turno, divididos por los segundos entre turnos.
- Mida primero la velocidad de un flujo individual, tanto en prefill como en decode. No use una cifra de la tarjeta de otra persona: mida los tokens por segundo en su propio equipo y use el resultado.
- Estime el ciclo de actividad. Veinte usuarios de chat, 12 segundos de generación por turno y un turno cada 90 segundos dan 20 * 12 / 90, es decir, aproximadamente 2.7 solicitudes en curso.
- Establezca un número de slots ligeramente superior a esa cifra y compruébelo con la memoria: el número de slots multiplicado por el contexto de cada solicitud debe caber en los tokens de caché disponibles.
- Mantenga corta la cola para que el desbordamiento falle rápido y de forma visible.
Los tokens de caché disponibles equivalen a la memoria libre después de cargar los pesos, dividida por el coste por token indicado en la sección anterior. Una tarjeta de 24 GB que ejecuta un modelo 8B en 16-bit utiliza aproximadamente 16 GB para los pesos y dispone de unos 6 GB de caché utilizable con la utilización predeterminada. Esto equivale aproximadamente a cinco conversaciones de 8K. Para admitir más conversaciones, reduzca el contexto por solicitud o almacene la caché en 8-bit (llama-server ocupa --cache-type-k q8_0). Ambas opciones aumentan la concurrencia a cambio de renunciar a algo. Conviene leer la descripción completa de ese equilibrio antes de invertir en hardware: cuándo un GPU VPS alcanza el punto de equilibrio frente a los tokens de una API.
Cuando los valores predeterminados de Ollama dejan de ser suficientes
Aumente el número de solicitudes simultáneas mediante la unidad del servicio, porque una exportación en el shell no llegará a un daemon administrado por systemd.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_MAX_QUEUE=64"sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment
ollama pssystemctl show debe mostrar las tres variables que acaba de establecer. Si no lo hace, el drop-in no se guardó y ninguna otra acción tendrá efecto. ollama ps muestra después el modelo cargado con un tamaño superior al de los pesos por sí solos, porque cuatro slots de 8,192 tokens reservan 32,768 tokens de caché además de ellos. Si la columna PROCESSOR muestra parte del modelo en la CPU cuando esperaba que todo se ejecutara en la GPU, significa que solicitó más caché de la que quedaba disponible en la tarjeta. Reduzca uno de los dos valores. Normalmente, reducir el contexto es la opción más segura, pero una ventana demasiado pequeña trunca silenciosamente los prompts largos en lugar de generar un error. Por eso conviene dimensionar num_ctx de forma deliberada en vez de reducirlo hasta que el modelo quepa.
El valor predeterminado de la cola merece una segunda revisión. Ollama pone en cola hasta OLLAMA_MAX_QUEUE solicitudes, y «el valor predeterminado es 512». Después de ese límite, responde «con un error 503 que indica que el servidor está sobrecargado». Una cola de 512 solicitudes en un equipo que atiende cuatro a la vez es una promesa que no puede cumplir, porque el cliente situado en la posición 300 agota el tiempo de espera mucho antes de que llegue su turno. Una cola corta devuelve un error que la aplicación puede reintentar o informar, lo que es preferible a un indicador de carga que nunca termina.
Pruébelo en condiciones reales. Envíe dos solicitudes al mismo tiempo desde dos terminales y supervise ambas. Si la segunda no produce ninguna salida hasta que termina la primera, la configuración de paralelismo no se aplicó.
Cuando un motor de inferencia real empieza a compensar
vLLM compensa la configuración adicional cuando tiene una GPU con margen y más de aproximadamente cuatro solicitudes realmente en curso. Su planificador trabaja por token, su caché usa paginación para reutilizar los fragmentos libres y convierte la VRAM disponible en concurrencia en lugar de dejarla inactiva. En agosto de 2026, la instalación y el inicio documentados constan de dos comandos:
uv pip install vllm --torch-backend=auto
vllm serve Qwen/Qwen2.5-1.5B-Instructcurl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [{"role": "user", "content": "Say hello."}]
}'Una respuesta que contiene una matriz choices indica que el servidor está activo y que el modelo se ha cargado. Con carga, los dos parámetros importantes son --max-num-seqs, el «número máximo de secuencias que se procesan en una sola iteración», y --max-num-batched-tokens, el «número máximo de tokens que se pueden procesar en una sola iteración». El primero limita la concurrencia. El segundo define el presupuesto de prellenado por bloques descrito anteriormente.
Con menos de aproximadamente cuatro solicitudes en curso, o en cualquier equipo sin una GPU compatible, vLLM añade complejidad y aporta poco. Requiere una tarjeta de clase CUDA y reclama la mayor parte de la memoria al arrancar, un intercambio inadecuado en un VPS de 4 a 8 GB. En ese caso, la opción adecuada es un modelo más pequeño, con un contexto más corto y una cola que usted controle. cómo se diferencian Ollama y vLLM como motores de inferencia explica la elección en detalle, y ejecutar Qwen 3 8B en un VPS muestra lo que exige un modelo de tamaño medio antes de añadir un solo usuario adicional.
El costo que oculta la creencia popular
El batching continuo aumenta el rendimiento total y normalmente también mejora la latencia mediana, porque una solicitud en cola empieza antes. La latencia de cola evoluciona en sentido contrario, y esa parte rara vez se menciona.
Cada secuencia adicional en un paso añade algo de trabajo, por lo que el ITL aumenta para todos a medida que se llena el batch. El prefill de una nueva solicitud ocupa parte de un paso que, de otro modo, habrían usado las solicitudes en streaming. Bajo presión de caché, el planificador interrumpe la ejecución, y una solicitud generada parcialmente vuelve al inicio de su prefill.
Una interfaz de chat muestra las colas, no los promedios. Un stream que se pausa durante dos segundos en mitad de una frase parece roto, aunque el tiempo total hasta completar la respuesta sea bueno. Mida el TTFT p95 y el ITL p95 con la carga prevista, y trate la media de tokens por segundo como una medida de capacidad, no como una descripción de la experiencia.
La configuración práctica se deduce de esto. Limite la concurrencia ligeramente por debajo de lo que permite la memoria, para que el motor nunca tenga que interrumpir la ejecución. Una cola corta y predecible es mejor que un batch profundo que se atasca, porque un usuario que espera cuatro segundos y después recibe un stream fluido está más satisfecho que uno que empieza al instante y sufre dos pausas.
Qué comprobar cuando va lento
Cada usuario tiene un rendimiento normal, pero la espera es larga. Eso es una cola, no un problema de velocidad. Compruebe primero el ajuste de paralelismo. El modelo está atendiendo correctamente las solicitudes, una por una.
Ollama devuelve HTTP 503. La cola está llena. El equipo está realmente al límite de su capacidad o OLLAMA_MAX_QUEUE está configurado con un valor bajo de forma intencionada para descartar carga, que es precisamente su función.
Los tokens por segundo se desploman bajo carga en un equipo con CPU. Ejecute vmstat 1 mientras ocurre. Si las columnas si y so tienen valores distintos de cero, la máquina está usando swap y lee los pesos del disco para generar cada token. Ningún cambio de configuración puede resolverlo. Reduzca el tamaño del modelo o el número de slots.
Uno de cada diez usuarios espera mucho más que los demás. Busque preempted en el registro de vLLM. La preempción y el recálculo asociado son la causa habitual. Esto significa que la caché está sobredimensionada para la longitud de contexto permitida.
El TTFT es malo incluso cuando el servidor está inactivo. Eso es un problema de prefill, no de concurrencia. Los prompts largos requieren tiempo real antes de que aparezca el primer token. Revise primero el tamaño del prompt y el almacenamiento en caché del prefijo, antes que el hardware. Si la espera larga sólo afecta al primer usuario que vuelve después de un periodo de inactividad y todos los siguientes funcionan bien, no se trata de prefill. Ollama ha descargado el modelo y vuelve a leer los pesos del disco. Conviene descartarlo manteniendo el modelo residente entre solicitudes.
FAQ
¿Por qué mi LLM autohospedado se ralentiza cuando lo usa una segunda persona?
En la mayoría de los casos no se ralentiza. Se pone en cola. Ollama se distribuye con OLLAMA_NUM_PARALLEL establecido en 1, por lo que la segunda solicitud espera a que la primera emita su último token. Distinga ambos casos midiendo el flujo de tokens de un usuario mientras otro espera: si sus tokens por segundo son normales cuando empieza, hay una cola y aumentar el número de solicitudes paralelas lo soluciona. Si ambos flujos funcionan a la mitad de velocidad, realmente están compartiendo el ancho de banda de memoria y se trata de un límite del hardware.
¿Cuántos usuarios simultáneos puede atender una GPU pequeña?
Cuente la memoria, no los usuarios. Primero están los pesos y después la caché KV, cuyo coste es 2 por capas por cabezas de clave/valor por dimensión de cabeza por bytes, por token y por conversación activa. Un modelo 8B típico con 36 capas, 8 cabezas de clave/valor y una dimensión de cabeza de 128 consume aproximadamente 144 KiB por token en 16 bits, por lo que una conversación de 8,192 tokens necesita aproximadamente 1.2 GB. Una tarjeta de 24 GB que mantenga ese modelo en 16 bits dispone de unos 6 GB para la caché, lo que permite unas cinco conversaciones con el contexto completo, o más si reduce el contexto.
¿El batching continuo hace que la respuesta de cada usuario sea más lenta?
La latencia mediana suele mejorar porque las solicitudes dejan de esperar a que termine todo un lote. La latencia de cola empeora. Cada secuencia adicional añade trabajo a cada paso de decodificación, la fase de prefilling de una nueva llegada ocupa parte de un paso que correspondía a los usuarios que reciben el flujo, y una solicitud desalojada debe ejecutar el prefilling dos veces. Mida la latencia p95 entre tokens, no el promedio, porque una ventana de chat hace visibles las pausas de una forma que los promedios ocultan.
¿Debo aumentar OLLAMA_NUM_PARALLEL o cambiar a vLLM?
Aumente primero el número de solicitudes paralelas. No tiene coste y sólo requiere un archivo de sustitución, además de solucionar el caso habitual en el que cuatro personas esperan detrás de una respuesta larga. La memoria es el límite: las solicitudes paralelas multiplican el contexto que debe mantener, así que supervise si algunas capas pasan a la CPU. Cambie a vLLM cuando tenga una GPU con VRAM disponible y más de unas cuatro solicitudes realmente en ejecución, ya que a partir de ese punto la caché paginada y la planificación por token ofrecen más ventajas que costes.
¿Más núcleos de CPU solucionarán un servidor LLM lento?
No en la parte que más perciben los usuarios. La decodificación lee todo el modelo desde la memoria para cada token, por lo que está limitada por el ancho de banda de la RAM. Los núcleos adicionales dejan de ayudar cuando se satura el ancho de banda. El prefilling sí escala con los núcleos, por lo que un número mayor reduce el tiempo hasta el primer token en prompts largos. En una VPS de 4 a 8 GB, la limitación principal suele ser la capacidad de memoria. La solución efectiva suele ser un modelo más pequeño o un contexto más corto, no más vCPU.