Caso real IA local
IA local en una VPS sin GPU: qué modelos funcionan y a qué velocidad (lo medimos)
Medimos seis modelos (Qwen3.5, Gemma 4, Ministral 3 y Llama 3.2) con llama.cpp en una VPS de 3 vCPU sin GPU: velocidad real, calidad y para qué sirve.
Probado el 17 de octubre de 2026 en llama.cpp b11714 (CPU x64, backend haswell) · Windows Server 2022, AMD Ryzen 9 5900X con 3 vCPU, 12 GB de RAM, sin GPU. Todas las cifras de velocidad propias salen de llama-bench (3 repeticiones) y llama-cli en esa VPS. Las de otros equipos se citan con su fuente. Cómo probamos
En este artículo
En una VPS normal, sin tarjeta gráfica, puedes ejecutar modelos de lenguaje de hasta unos 4.000 millones de parámetros a una velocidad usable: en la nuestra, con 3 vCPU de un Ryzen 9 5900X y 12 GB de RAM, seis modelos generaron entre 6,7 y 24,9 tokens por segundo. Sirven para clasificar, extraer datos o resumir textos cortos. No sirven para razonar ni para programar sin revisar, ni para sustituir a un modelo grande de pago: de los cinco a los que se la pedimos, solo uno escribió bien a la primera una función de Python sencilla, y el más pequeño explicó mal un concepto básico.
Lo medimos el 17 de octubre de 2026 con llama.cpp, la build b11714, en la misma VPS con Windows Server 2022 en la que funciona nuestro asistente. Aquí tienes las cifras, las respuestas tal cual, cómo repetirlo y para qué tareas compensa.
La máquina y cómo medimos
- CPU: AMD Ryzen 9 5900X, pero la VPS solo ve 3 vCPU. llama.cpp cargó su backend de CPU para instrucciones AVX2 («haswell»).
- RAM: 12 GB, de los que había unos 6,5 GB libres con el resto de servicios en marcha.
- GPU: ninguna. El adaptador de vídeo es el genérico de Windows.
- Disco libre: entre 1,4 y 8 GB según el momento. Esto marcó qué pudimos probar: un modelo cada vez, descargarlo, medirlo y borrarlo.
Para cada modelo hicimos dos cosas:
llama-bench -t 3 -p 512 -n 128 -r 3: procesa un prompt de 512 tokens (pp512) y genera 128 tokens (tg128), tres veces, y da la media con su desviación.- Dos preguntas reales con
llama-cli, temperatura baja y el modo de razonamiento desactivado (-rea off): una explicación en español para alguien no técnico y una función de Python.
Todos los modelos en cuantización Q4_K_M, el punto de equilibrio habitual: según la tabla oficial de llama.cpp con Llama 3 8B, empeora la perplejidad un 2,8 % frente al modelo sin comprimir y ocupa menos de un tercio.
Los resultados
| Modelo (Q4_K_M) | Fichero | Prompt (pp512) | Generación (tg128) | Explicación | Función de Python |
|---|---|---|---|---|---|
| Qwen3.5 0.8B | 0,53 GB | 191,5 ± 4,5 t/s | 24,9 ± 1,0 t/s | Falsa | Inservible |
| Qwen3.5 2B | 1,28 GB | 69,1 ± 8,6 t/s | 13,5 ± 0,5 t/s | Correcta | Dos errores |
| Ministral 3 3B | 2,15 GB | 35,5 ± 1,7 t/s | 8,0 ± 0,1 t/s | Con un error | Funciona, con una regla inventada |
| Llama 3.2 3B Instruct | 2,02 GB | 41,2 ± 0,4 t/s | 8,9 ± 0,1 t/s | Vaga | No la pedimos |
| Gemma 4 E2B | 3,11 GB | 54,1 ± 3,4 t/s | 9,0 ± 2,4 t/s | Correcta | Correcta |
| Qwen3.5 4B | 2,74 GB | 34,2 ± 0,9 t/s | 6,7 ± 0,1 t/s | La mejor | Falla con el primer fichero |
La desviación alta de Gemma 4 E2B en generación se debe a que durante esa medición había otro proceso usando la CPU; en sus dos respuestas con llama-cli, ya sin él, generó a 11,3 y 11,8 tokens por segundo.
Para traducir esas cifras a algo tangible: una respuesta de unas 300 palabras en español son unos 400 tokens. Con el 2B tarda alrededor de medio minuto en escribirse; con Qwen3.5 4B, cerca de un minuto. A eso súmale lo que tarda en leer tu pregunta, que con prompts largos sí se nota: un documento de 4.000 tokens son más de minuto y medio de procesado con un modelo de 3-4B antes de que salga la primera palabra.
Un detalle de nombres que confunde: Gemma 4 E2B no es un modelo de 2.000 millones de parámetros. La «E» es de «efectivos»: llama.cpp cuenta 4.650 millones y el fichero ocupa más que el de Qwen3.5 4B. Mira siempre el tamaño del fichero, no el nombre.
Lo que respondieron
Pedimos: «Explica en tres frases, en español y para alguien que no es técnico, qué es la cuantización de un modelo de lenguaje y qué se pierde con ella».
- Qwen3.5 0.8B: «La cuantización es un proceso donde un modelo de lenguaje reduce la cantidad de palabras que puede generar…». Es falso. La cuantización reduce la precisión de los números que forman el modelo, no su vocabulario. Suena bien y está mal, que es el peor tipo de error.
- Qwen3.5 2B: «…reduce el número de bits de información en los que se guardan los cálculos de un modelo de lenguaje, haciendo que funcione más rápido y consuma menos memoria. Al hacer esto, el modelo pierde una pequeña cantidad de precisión matemática…». Correcto y claro.
- Llama 3.2 3B: habló de «reducir la complejidad», «valores discretos» y de que «se pierde la capacidad de captar información continua». Vago, más jerga que explicación.
- Ministral 3 3B: explicó bien lo de reducir la precisión de los números, pero añadió que el modelo puede volverse «más lento». Es al revés: cuantizar lo hace más rápido.
- Gemma 4 E2B: «…se hace reduciendo la precisión de los números que el modelo usa para procesar el lenguaje. Como resultado, se pierde un poco de la sutileza…». Correcto.
- Qwen3.5 4B: «La cuantización es como pasar de tener una foto en alta definición a una versión comprimida en menor calidad para que ocupe menos espacio y cargue más rápido. Con este proceso, se redondean los números que el modelo utiliza…». La mejor de las seis: exacta y con una comparación que entiende cualquiera.
Y la función de Python (recibir rutas y devolver un diccionario con el tamaño total por extensión, ignorando las que no existan):
- Qwen3.5 0.8B escribió una función que recibe una sola ruta y devuelve su tamaño mal calculado. Inservible.
- Qwen3.5 4B importó
osy sumaba bien, pero escribió_, _, extensión = os.path.splitext(ruta): desempaqueta tres valores de una función que devuelve dos, así que falla con el primer fichero que existe. - Ministral 3 3B entregó una función que funciona, pero que se salta los ficheros sin extensión y, en ese caso, busca una «extensión» en el nombre de la carpeta. Nadie se lo pidió.
- Gemma 4 E2B fue el único que la escribió bien a la primera: importa
os, comprueba que la ruta existe, pasa la extensión a minúsculas y suma por extensión. Además añadió un ejemplo de uso que no le pedimos y que se cortó al llegar al límite de 400 tokens.
El caso del 2B es el más instructivo, porque el código parece correcto a primera vista:
def calcular_tamano_rutas(rutas):
diccionario = {}
for ruta in rutas:
try:
if os.path.exists(ruta):
tamaño = os.path.getsize(ruta)
ext = os.path.splitext(ruta)[1]
diccionario[ext] = tamaño
except (OSError, IOError):
pass
return diccionario
Parece correcto y tiene dos fallos: falta import os, así que no se ejecuta, y diccionario[ext] = tamaño sobrescribe en lugar de sumar, de modo que con dos ficheros .txt solo cuenta el último. Lo repetimos en dos ejecuciones distintas y cometió los mismos dos errores las dos veces.
Por qué va a esta velocidad
Hay dos fases y dependen de cosas distintas:
- Leer el prompt (pp) es cálculo puro: multiplica matrices con muchos tokens a la vez. Depende de cuántos núcleos tienes y de sus instrucciones vectoriales. Por eso aquí salen decenas de tokens por segundo.
- Generar (tg) produce un token cada vez y, para cada uno, tiene que leer de la memoria todos los pesos del modelo. El límite es el ancho de banda de la memoria, no la CPU. La regla aproximada: tokens por segundo ≈ ancho de banda ÷ tamaño del modelo.
Por eso el salto de 0,53 GB a 2,02 GB de fichero divide la velocidad de generación casi por tres (de 24,9 a 8,9 tokens por segundo), y por eso en una VPS compartes con los demás clientes del servidor físico tanto los núcleos como el ancho de banda. Como referencia, Corsair calcula que un PC de sobremesa con DDR5-5600 en doble canal ronda los 90 GB/s, lo que deja un techo teórico de unos 18 tokens por segundo con un modelo de 8.000 millones en Q4_K_M.
Otras mediciones públicas solo con CPU, para situar las nuestras:
| Equipo | Modelo | Generación | Fuente |
|---|---|---|---|
| Portátil Framework 13, Ryzen AI 5 340 | Llama 3.2 3B (Ollama) | 23,8 t/s | Jeff Geerling |
| Mini PC con Intel N150 | Llama 3.2 3B (Ollama) | 9,1 t/s | Jeff Geerling |
| Raspberry Pi 5 | Llama 3.2 3B (Ollama) | 4,9 t/s | Jeff Geerling |
| Portátil Framework 13, Ryzen AI 5 340 | DeepSeek R1 14B (Ollama) | 5,8 t/s | Jeff Geerling |
| Placa ARM Radxa Orion O6, 64 GB | Qwen3-30B-A3B Q4_K_M (MoE) | 15-16,8 t/s | Foro de Radxa |
| Nuestra VPS, 3 vCPU | Llama 3.2 3B Q4_K_M | 8,9 t/s | Medición propia |
Nuestra VPS queda al nivel de un mini PC con un Intel N150 con el mismo modelo. Tres núcleos virtuales de un procesador de escritorio no son un portátil moderno con todos sus núcleos para él.
La excepción: modelos MoE si tienes mucha RAM
La última fila de esa tabla es la interesante para un servidor sin GPU. Los modelos de mezcla de expertos (MoE), como Qwen3-30B-A3B o gpt-oss-20b, tienen muchos parámetros pero solo activan una parte por cada token: unos 3.000 millones en Qwen3-30B-A3B y 3.600 millones en gpt-oss-20b. La memoria tiene que caber entera, pero la velocidad de generación se parece a la de un modelo denso pequeño.
En la placa de Radxa, solo con CPU, Qwen3-30B-A3B genera a 15-16,8 tokens por segundo, más que un modelo denso de 14.000 millones en un portátil más rápido. Con un modelo así tienes la calidad de un modelo mediano a la velocidad de uno pequeño, siempre que la VPS tenga la RAM:
- Qwen3-30B-A3B en Q4_K_M ocupa 18,63 GB de fichero.
- gpt-oss-20b necesita 14,9 GB en total con 8.000 tokens de contexto, según las medidas de llama.cpp.
En nuestra VPS de 12 GB no caben, así que no lo hemos podido comprobar. En una de 32 GB es la primera prueba que haríamos.
Cuánta RAM hace falta
La memoria que necesitas es aproximadamente el tamaño del fichero del modelo, más la caché KV (que crece con el contexto), más algo de margen para el programa y el sistema. Hugging Face da la referencia de Llama 3.1 8B: la caché ocupa unos 0,125 GB con 1.000 tokens de contexto y casi 2 GB con 16.000.
| RAM de la VPS | Qué cabe con holgura (Q4_K_M) | Generación orientativa |
|---|---|---|
| 4 GB | Modelos de 1-2B (Qwen3.5 0.8B y 2B) | 13,5-24,9 t/s en 3 vCPU (medido) |
| 8 GB | Hasta 3-4B (Gemma 4 E2B, Qwen3.5 4B, Ministral 3 3B) | 6,7-9 t/s en 3 vCPU (medido) |
| 16 GB | Modelos de 8-9B (Qwen3.5 9B) con contexto moderado | Menos que un 3B; no lo medimos |
| 32 GB o más | MoE como Qwen3-30B-A3B o gpt-oss-20b | 15-17 t/s en la placa de Radxa (fuente externa) |
Deja siempre margen para lo que ya corre en el servidor. Si la VPS empieza a usar el archivo de intercambio, la velocidad se hunde.
Cómo repetirlo en tu VPS
En Linux es igual que en Windows cambiando el binario.
- Descarga llama.cpp ya compilado de la página de versiones de GitHub (en Windows, el zip de CPU x64; en Linux, el equivalente o
brew install llama.cpp). No necesita instalación. - Comprueba el disco libre antes de bajar nada. Un 3B en Q4_K_M son 2 GB.
- Descarga el modelo en GGUF desde Hugging Face:
curl -L -o gemma-4-e2b.gguf \ https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-Q4_K_M.gguf - Mide, con tantos hilos como vCPU tengas:
llama-bench -m gemma-4-e2b.gguf -t 3 -p 512 -n 128 -r 3 - Pruébalo con tus tareas reales, no con preguntas genéricas (
-rea offdesactiva el razonamiento en los modelos que lo tienen):llama-cli -m gemma-4-e2b.gguf -t 3 -c 4096 -st -rea off --temp 0.2 \ -p "Clasifica este correo como factura, soporte o spam: ..." - Sírvelo como API solo en la interfaz local:
Desde tu ordenador, llega con un túnel SSH (llama-server -m gemma-4-e2b.gguf -t 3 -c 4096 --host 127.0.0.1 --port 8080ssh -L 8080:127.0.0.1:8080 tu-vps). No abras ese puerto a internet: sin--api-key, cualquiera que llegue al puerto puede usarlo.
Para qué sirve de verdad (y para qué no)
Tareas donde un modelo pequeño en CPU tiene sentido:
- Clasificar correos, tickets o comentarios en una lista cerrada de categorías.
- Extraer campos de un texto a JSON (nombre, fecha, importe) cuando validas el resultado.
- Resumir textos cortos para uso interno.
- Datos que no pueden salir de tu servidor por privacidad o contrato.
- Transcribir audio con whisper.cpp, que también corre en CPU. No lo medimos en esta VPS; su documentación indica unos 3,9 GB de RAM para el modelo grande.
Donde no compensa:
- Programar: lo has visto con la función de Python. Comparamos los modelos de código que sí merecen la pena (y que necesitan GPU o un Mac con mucha memoria) en modelos locales para programar frente a Claude.
- Asistentes y agentes que encadenan herramientas, necesitan contexto largo y deben equivocarse poco. Nuestro asistente de servidores usa Claude por eso; lo contamos en cómo automatizamos servidores con IA.
- Cualquier cosa de cara a clientes sin revisión humana.
¿Y el coste?
Si ya pagas la VPS, ejecutar el modelo no te cuesta dinero extra, pero sí CPU: durante la generación ocupa todos los núcleos que le des. Compáralo con la API más barata de Anthropic, Claude Haiku 5.5, a 0,10 $ por millón de tokens de entrada y 0,50 $ por millón de salida (con prompts de hasta 100.000 tokens). Clasificar 10.000 correos de 300 tokens con una respuesta de 10 tokens son unos 3 millones de tokens de entrada: unos 0,35 $ con la API, frente a entre 20 y 25 horas de CPU de la VPS al 100 % solo para leer esos textos con un modelo de 3-4B, según nuestras velocidades de procesado de prompt. Para volumen bajo y datos que pueden salir del servidor, la API gana. La IA local en una VPS sin GPU compensa cuando los datos no deben salir o cuando ya tienes la máquina ociosa.
Qué hacer ahora
- Mira cuánta RAM libre tiene tu VPS de verdad, con los servicios en marcha.
- Prueba Gemma 4 E2B o Qwen3.5 4B con los pasos de arriba y tus propias tareas (si la RAM no da, Qwen3.5 2B): diez ejemplos reales dicen más que cualquier benchmark.
- Si te falta calidad y tienes 32 GB o más, prueba un modelo MoE antes de pensar en una GPU.
- Si dudas entre herramientas, lee Ollama, llama.cpp o LM Studio. Para un servidor sin GPU, nosotros usamos llama.cpp.
- Para elegir modelo según otro tipo de máquina, tienes los mejores modelos de IA local según tu equipo.