Ejecutar modelos de lenguaje en local se ha vuelto cada vez más accesible, pero elegir el motor de inferencia adecuado sigue siendo una decisión importante. Dos de las opciones más interesantes son vLLM y llama.cpp. Aunque ambos permiten ejecutar y servir LLM, están diseñados con prioridades bastante diferentes.
Después de trabajar con ambos, mi conclusión es que no existe un ganador absoluto: vLLM destaca como servidor de inferencia sobre GPU, mientras que llama.cpp ofrece una flexibilidad difícil de igualar para ejecutar modelos cuantizados en prácticamente cualquier hardware.
vLLM: rendimiento y serving sobre GPU
vLLM está pensado principalmente para servir modelos de forma eficiente sobre GPU. Puede cargar directamente modelos distribuidos mediante Hugging Face y ofrece una API compatible con OpenAI, lo que facilita integrarlo con aplicaciones y agentes existentes.
Una de sus principales ventajas es la gestión eficiente de la memoria mediante PagedAttention, junto con técnicas de batching que permiten aprovechar mejor la GPU cuando existen varias peticiones simultáneas.
También ofrece características especialmente interesantes en equipos dedicados a IA:
- Tensor Parallel para distribuir modelos entre varias GPU.
- Cuantización FP8.
- KV Cache en formatos de menor precisión.
- Continuous batching.
- Speculative decoding.
- API compatible con OpenAI.
- Buen rendimiento con múltiples peticiones concurrentes.
En sistemas con varias GPU, vLLM permite repartir un modelo mediante Tensor Parallel. Esto hace posible ejecutar modelos que no cabrían en una única tarjeta y aprovechar conjuntamente la VRAM disponible.
Su principal inconveniente es que resulta bastante más exigente en cuanto a compatibilidad de modelos y hardware. Las arquitecturas nuevas pueden necesitar soporte específico y determinados modelos cuantizados no siempre funcionan inmediatamente.
llama.cpp: flexibilidad y GGUF
llama.cpp parte de una filosofía diferente. Su gran fortaleza es poder ejecutar modelos en formato GGUF utilizando CPU, GPU o una combinación de ambas.
Esto permite utilizar diferentes niveles de cuantización —Q4, Q5, Q6, Q8, entre otros— y adaptar el modelo a la memoria disponible.
Por ejemplo, un modelo que necesitaría alrededor de 60 GB en BF16 puede reducir considerablemente sus requisitos mediante una cuantización GGUF, manteniendo una calidad sorprendentemente próxima al modelo original cuando se utilizan cuantizaciones altas como Q8.
Otra ventaja importante es el offloading. Si el modelo no cabe completamente en VRAM, parte de sus capas pueden mantenerse en RAM y ejecutarse mediante CPU. El rendimiento disminuye, pero permite trabajar con modelos que simplemente serían imposibles de cargar completamente en GPU.
llama.cpp destaca especialmente por:
- Amplio soporte del formato GGUF.
- Gran variedad de cuantizaciones.
- Ejecución mediante CPU y GPU.
- Offloading parcial a GPU.
- Requisitos de hardware relativamente bajos.
- Compatibilidad con numerosas arquitecturas.
- API compatible con OpenAI mediante
llama-server.
Para experimentar con modelos locales resulta especialmente práctico: descargar un GGUF y comenzar a probarlo suele ser mucho más sencillo que preparar un entorno completo de serving mediante GPU.
FP8 frente a GGUF
Una diferencia importante entre ambos ecosistemas está en el tipo de cuantización utilizado.
vLLM está especialmente orientado a formatos utilizados directamente por aceleradores, como BF16 y FP8. llama.cpp, por el contrario, utiliza principalmente las cuantizaciones definidas dentro del ecosistema GGUF.
Un modelo FP8 suele necesitar aproximadamente la mitad de memoria destinada a pesos que su equivalente BF16. GGUF permite reducirla todavía más mediante cuantizaciones como Q6, Q5 o Q4.
De forma simplificada:
| Formato | Memoria | Calidad | Uso habitual |
|---|---|---|---|
| BF16 | Muy alta | Máxima | GPU con mucha VRAM |
| FP8 | Alta | Muy alta | Serving GPU |
| GGUF Q8 | Alta | Muy alta | Inferencia local |
| GGUF Q6/Q5 | Media | Alta | Equilibrio calidad/memoria |
| GGUF Q4 | Baja | Buena | Hardware limitado |
No obstante, comparar FP8 y GGUF únicamente por el tamaño del archivo sería un error. La arquitectura del modelo, la implementación de los kernels, el tamaño del contexto y la KV Cache también influyen considerablemente en el consumo real de memoria y en el rendimiento.
¿Cuál ofrece más rendimiento?
Cuando el modelo cabe completamente en GPU y el hardware está bien soportado, vLLM suele ser la opción más adecuada para ofrecer un servicio de inferencia de alto rendimiento, especialmente cuando existen varias peticiones concurrentes.
llama.cpp puede ofrecer velocidades excelentes, pero su principal ventaja no está necesariamente en conseguir el máximo throughput, sino en su flexibilidad.
La diferencia se vuelve especialmente clara cuando el servidor debe atender simultáneamente a varios usuarios. Las técnicas de batching y gestión de memoria utilizadas por vLLM permiten aprovechar mucho mejor la GPU en este escenario.
Para uso individual, desarrollo o experimentación, esa ventaja puede resultar mucho menos importante.
Multi-GPU
Otro punto interesante aparece cuando disponemos de varias GPU.
vLLM puede utilizar Tensor Parallel para distribuir el modelo entre diferentes tarjetas. No es imprescindible disponer de NVLink: también puede funcionar mediante PCIe, aunque la comunicación entre GPU puede convertirse en un factor limitante.
llama.cpp también permite repartir el modelo entre varias GPU, aunque su enfoque sigue estando más orientado a conseguir ejecutar el modelo con los recursos disponibles que a maximizar el throughput de un servidor con muchas peticiones.
En ambos casos, sumar dos GPU de 24 GB no convierte literalmente el sistema en una única GPU de 48 GB. La forma en que se distribuyen los pesos, la KV Cache y las operaciones entre dispositivos importa tanto como la cantidad total de VRAM.
¿Cuál elegir?
La elección depende principalmente del objetivo.
Elegiría vLLM cuando:
- El modelo cabe completamente en GPU.
- Quiero utilizar modelos BF16 o FP8.
- Necesito atender múltiples peticiones.
- Quiero aprovechar varias GPU.
- Estoy desplegando una API para otras aplicaciones.
- El rendimiento y el throughput son prioritarios.
Elegiría llama.cpp cuando:
- Quiero utilizar modelos GGUF.
- La VRAM disponible es limitada.
- Necesito combinar RAM y VRAM.
- Quiero experimentar rápidamente con diferentes cuantizaciones.
- Busco máxima compatibilidad con hardware y modelos.
- La sencillez tiene más importancia que el throughput máximo.
Conclusión
vLLM y llama.cpp no son realmente competidores directos en todos los escenarios.
vLLM se aproxima más a una plataforma de serving de alto rendimiento, diseñada para aprovechar aceleradores y atender eficientemente múltiples peticiones. llama.cpp es una herramienta de inferencia extraordinariamente flexible, capaz de ejecutar modelos grandes incluso en equipos donde los recursos disponibles son limitados.
En una estación de trabajo dedicada a IA, tiene sentido utilizar ambos.
Para modelos que funcionan correctamente en FP8 y caben completamente en las GPU, vLLM puede proporcionar un entorno de serving rápido y eficiente. Para probar nuevos modelos, utilizar GGUF, experimentar con distintas cuantizaciones o ejecutar modelos que exceden la VRAM disponible, llama.cpp continúa siendo una de las herramientas más versátiles del ecosistema de IA local.
La pregunta, por tanto, no es tanto «¿vLLM o llama.cpp?», sino «¿qué herramienta encaja mejor con este modelo y este escenario de inferencia?».