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?
Cuando un LLM autohospedado se bloquea con 5 usuarios simultáneos, la causa habitual es que el servidor está configurado para generar una respuesta cada vez y las otras cuatro están en una cola. La documentación de Ollama es clara sobre su valor predeterminado: OLLAMA_NUM_PARALLEL es «el número máximo de solicitudes en paralelo que procesará cada modelo al mismo tiempo; el valor predeterminado es 1». No hay ningún componente averiado y el software de servicio puede trabajar con varias solicitudes a la vez. Cuatro de las cinco personas esperan su turno porque una configuración lo establece así.
La solución rara vez consiste en usar un equipo más potente. Se necesita un motor de servicio que procese muchas solicitudes en el mismo paso hacia delante del modelo y suficiente memoria disponible para mantener las conversaciones de todos los usuarios mientras lo hace. Ambas partes importan, pero la segunda es la que realmente establece 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 «whether to enable continuous batching (a.k.a dynamic batching) (default: enabled)», incluye «Parallel decoding with multi-user support» entre sus funciones y, desde un cambio integrado en noviembre de 2025, se inicia con 4 slots de forma predeterminada (-np tiene -1 como valor predeterminado, lo que activa el modo automático). vLLM se basa en esta idea. 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 puede gestionar concurrencia, cuando en realidad era su configuración la que la desactivaba.
Los resultados publicados sobre batching continuo suelen medirse en tarjetas de centros de datos que disponen tanto de capacidad de cálculo libre como de decenas de gigabytes para la caché. El comportamiento general de esos resultados también se aplica a su equipo. Sus magnitudes no. La sección de memoria siguiente 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), y permite que la fase de decodificación no tenga que volver a calcular todo el prompt para cada token nuevo. El número de valores almacenados por token lo fija 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 y por la dimensión de cada cabeza. Consulte esos valores en config.json del modelo. Multiplíquelos por los bytes de cada valor para obtener el tamaño. Este último factor es un ajuste del runtime, no una propiedad del modelo: llama-server almacena la caché en f16 (2 bytes) de forma predeterminada y admite tipos más pequeños, como q8_0, mediante -ctk y -ctv.
Haga el cálculo una vez y el límite deja de ser una incógnita. Un modelo 8B típico, con 36 capas, 8 cabezas de clave/valor y una dimensión de cabeza de 128, usando 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, aproximadamente 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 paralelo de solicitudes 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 tendrá un contexto de 8K y requerirá una asignación de memoria adicional." La RAM necesaria escala con OLLAMA_NUM_PARALLEL multiplicado por OLLAMA_CONTEXT_LENGTH. En llama-server, el número predeterminado de slots en modo automático ejecuta todos los slots sobre un único búfer KV unificado. Por tanto, todo el contexto de -c forma un único grupo del que extraen memoria los slots. Si establece -np manualmente, el búfer unificado se desactiva, a menos que también pase --kv-unified. En ese caso, el contexto solicitado mediante -c se reparte entre los -np slots, y aumentar por sí solo el número de slots reduce el contexto disponible para 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 (0.92 de forma predeterminada) es "la fracción de memoria de GPU que utilizará el ejecutor del modelo". Si no establece --kv-cache-memory-bytes, vLLM calcula el tamaño de la caché KV a partir de esa fracción. El presupuesto restante, después de descontar los pesos y la memoria de trabajo del motor medida durante el perfilado, se convierte en el grupo KV paginado. Cuando ese grupo se queda sin espacio, el planificador expulsa una solicitud en lugar de hacerla fallar:
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 desalojada 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. Establezca disable_log_stats=False para registrar el contador acumulado o consulte 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 hacen solicitudes simultáneas o sólo han iniciado sesión?
Calcule las solicitudes en curso antes de dimensionar nada. La aritmética es sencilla: las solicitudes en curso son iguales al número de usuarios multiplicado por los segundos que tarda en generarse cada turno, dividido por los segundos entre turnos.
- Mida primero la velocidad de un flujo individual en su propio sistema, tanto en prefill como en decode. No use el valor de la tarjeta de otra persona: mida los tokens por segundo en su propio equipo y utilice 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.
- Configure un número de slots ligeramente superior a ese valor y compárelo con la memoria: el número de slots multiplicado por el contexto por solicitud debe caber en los tokens de caché disponibles.
- Mantenga corta la cola para que el exceso falle rápido y de forma visible.
Los tokens de caché disponibles son 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 usa aproximadamente 16 GB para los pesos y dispone como máximo de unos 6 GB de caché utilizable con la utilización predeterminada. La cantidad es algo menor cuando se reserva memoria de trabajo, lo que 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 toma --cache-type-k q8_0). Ambas opciones aumentan la concurrencia a cambio de renunciar a algo, y conviene leer la explicación completa de esa compensación antes de invertir en hardware: cuándo un VPS con GPU alcanza el punto de equilibrio frente a los tokens de 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 empieza a justificar su coste
vLLM compensa la configuración adicional cuando tiene una GPU con margen disponible 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 octubre de 2026, la instalación y el arranque documentados para GPU requieren tres comandos. vllm download-kernels descarga kernels precompilados que, de otro modo, vLLM descargaría y compilaría al iniciar:
uv pip install vllm --torch-backend=auto
vllm download-kernels
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 un arreglo 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 fragmentos descrito antes.
Con menos de aproximadamente cuatro solicitudes en curso, vLLM añade complejidad y ofrece pocos beneficios. Ya no es necesaria una GPU: en octubre de 2026, la guía de instalación para CPU documenta la «inferencia y el servicio básicos de modelos» en CPU x86 y Arm, con wheels x86 precompilados desde la versión 0.17.0 y una imagen Docker para CPU. Sin embargo, también conserva sus requisitos de memoria. En CPU aplica la misma fracción de utilización de 0.92 a la RAM del sistema y asigna lo que queda después de cargar los pesos a la caché KV. Por tanto, de forma predeterminada reclama la mayor parte de la memoria de la máquina al iniciar, salvo que limite la caché con --kv-cache-memory-bytes. En un VPS de 4 a 8 GB, esa no es una buena decisión. En ese caso, la opción adecuada es un modelo más pequeño, un contexto más corto y una cola bajo su control. diferencias entre Ollama y vLLM como motores de inferencia explica la elección en detalle, y ejecución de 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 autoalojado 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 petición espera a que la primera emita su token final. Distinga ambos casos midiendo el flujo de tokens de un usuario mientras otro espera: si la velocidad de tokens por segundo es normal cuando empieza, tiene una cola y aumentarla cantidad de ejecuciones paralelas lo soluciona. Si ambos flujos funcionan a media velocidad, realmente están compartiendo el ancho de banda de memoria y ese es un límite del hardware.
¿A cuántos usuarios simultáneos puede atender una GPU pequeña?
Cuente la memoria, no los usuarios. Primero se cargan los pesos y después la caché KV, cuyo coste por token y por conversación activa es 2 veces el número de capas por el número de cabezas de clave/valor por la dimensión de cabeza por el número de bytes. Un modelo típico de 8B 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 contiene ese modelo en 16 bits dispone como máximo de unos 6 GB para la caché. Eso equivale a unas cinco conversaciones con el contexto completo, o a 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 peticiones 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 prefill de una nueva petición ocupa parte de un paso que correspondería a los usuarios que reciben el flujo y una petición interrumpida debe ejecutar prefill 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 ejecuciones paralelas. No tiene coste y sólo requiere un archivo de sustitución directa. Además, soluciona el caso habitual en el que cuatro personas esperan detrás de una respuesta larga. La memoria es el límite: las peticiones paralelas multiplican el contexto que debe mantener, así que vigile si algunas capas pasan a la CPU. Cambie a vLLM cuando tenga una GPU con VRAM disponible y más de unas cuatro peticiones realmente en ejecución, porque 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 la lentitud del servidor LLM?
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 ese ancho de banda. La fase prefill sí escala con los núcleos, por lo que disponer de más núcleos reduce el tiempo hasta el primer token en prompts largos. En una VPS de 4 a 8 GB, la restricció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.