Después de dejar funcionando la parte de Bitcoin en el Mini PC, el siguiente paso era empezar a experimentar con modelos de lenguaje en local. En este terreno parto con bastante menos experiencia y no hay (o no conozco) guías especializadas como Minibolt en el caso de Bitcoin, así que la idea es avanzar poco a poco, entender qué hace cada pieza y comprobar hasta dónde puede llegar el hardware que ya tengo. Para recordar el punto de partida, el Mini PC sobre el que estoy haciendo estas pruebas cuenta con un hardware bastante modesto para este tipo de cargas, pero suficiente para empezar a experimentar con modelos locales:
- Un AMD Ryzen 7 8745H de CPU
- Una Radeon 780M integrada como GPU
- 32 GB de RAM DDR5.
llama.cpp
Como punto de partida elegí llama.cpp, un proyecto que permite ejecutar modelos de lenguaje de forma local sobre distintos tipos de hardware. Aunque existen binarios precompilados, preferí descargar el código fuente, del mismo modo que hice con Bitcoin Core. Esto permite tener más control sobre la versión utilizada y, sobre todo, sobre las opciones de compilación y los backends de aceleración disponibles.
La compilación se prepara con CMake. La opción -B indica en qué carpeta quiero generar los archivos del build. Para las pruebas mantengo dos compilaciones separadas: una normal para CPU y otra con soporte Vulkan (más tarde explicaré lo que es) para utilizar la Radeon 780M.
# CPU (build-cpu es el nombre de la carpeta)
$ cmake -B build-cpu
$ cmake --build build-cpu -j
# GPU: compilar llama.cpp con soporte Vulkan
$ cmake -B build-gpu -DGGML_VULKAN=ON
$ cmake --build build-gpu -j
El flag -DGGML_VULKAN=ON compila llama.cpp con soporte para Vulkan.
Entre los ejecutables generados me interesan principalmente tres:
llama-cli, para cargar un modelo e interactuar con él desde la terminal.llama-bench, para medir el rendimiento del modelo y comparar distintas configuraciones.llama-server, que más adelante permitirá levantar el modelo como un servicio accesible a través de una API.
Para mantener los modelos organizados he reservado el directorio /srv/llm/models.
Qwen

Qwen es una familia de modelos desarrollada por Alibaba Cloud. En sus versiones recientes se ha convertido en una de las principales familias de modelos de pesos abiertos junto a proyectos como DeepSeek. En la reciente carrera de la IA China parece haber apostado por el código abierto, algo a celebrar; no profundizaré mucho sobre el tema pero mi sensación es que los tech popes estadounidenses se han creido que le podían poner puertas al campo y se han llevado un buen chasco.
Los modelos que voy a descargar para mi MiniPC están muy lejos de los grandes modelos actuales de Anthropic y OpenAI como Claude Fable 5 o GPT Sol 5.6, pero si son comparables a modelos de hace un par de años como GPT4 o Claude 3 Haiku, lo que no es moco de pavo teniendo en cuenta que mi MiniPC es de uso generalista.
La familia Qwen3 incluye modelos densos y modelos Mixture of Experts (MoE), además de variantes de distintos tamaños. Voy a utilizar modelos densos de 8B y 14B parámetros, ambos en una versión cuantizada a 4 bits (Q4_K_M), y el modelo 8B cuantizado a 8 bits (Q8_0).
Descarga y ejecución de los modelos
llama.cpp puede descargar directamente un modelo desde Hugging Face y guardarlo en su caché local. Es la opción más sencilla:
# Ejecución descargando el modelo automáticamente desde Hugging Face
$ ./build/bin/llama-cli -hf Qwen/Qwen3-8B-GGUF:Q4_K_M
Yo he preferido descargar los archivos .gguf de forma explícita y guardarlos en /srv/llm/models, porque así sé exactamente qué modelos tengo instalados, cuánto ocupan y dónde se encuentran:
# Descarga explícita del archivo GGUF
$ wget https://huggingface.co/Qwen/Qwen3-8B-GGUF/resolve/main/Qwen3-8B-Q4_K_M.gguf \
-O /srv/llm/models/Qwen3-8B-Q4_K_M.gguf
# Ejecución del modelo descargado
$ ./build/bin/llama-cli -m /srv/llm/models/Qwen3-8B-Q4_K_M.gguf
Cuantización y número de parámetros
Antes de descargar los modelos conviene distinguir dos conceptos ya mencionados anteriormente: el número de parámetros y la cuantización.
Un mismo modelo, como Qwen3, puede encontrarse en versiones de distintos tamaños. Normalmente se identifican con cifras como 8B, 14B, etc, donde la B hace referencia a miles de millones de parámetros. De forma muy simplificada, cuantos más parámetros tiene un modelo, mayor es su capacidad para representar relaciones complejas y, en general, mejores pueden ser sus respuestas. A cambio, necesita más memoria y más capacidad de cálculo.
La cuantización actúa sobre esos parámetros. Consiste en almacenarlos con menor precisión numérica para reducir el tamaño del archivo y los recursos necesarios para ejecutar el modelo. Una cuantización más agresiva permite ahorrar bastante memoria, pero también puede introducir cierta pérdida de calidad.
Por tanto, al descargar un modelo no solo hay que elegir cuántos parámetros queremos, sino también con qué cuantización. En la práctica se trata de buscar un equilibrio entre calidad, memoria disponible y velocidad de ejecución.
Benchmark
Para medir el rendimiento utilicé llama-bench.
Las dos pruebas principales son:
pp512, que mide la velocidad con la que el modelo procesa un prompt de 512 tokens.tg128, que mide la velocidad de generación de 128 tokens nuevos.
Los resultados se expresan en tokens por segundo (t/s).
Qwen3 8B Q4_K_m
Este modelo tiene unos 8,19 mil millones de parámetros, está cuantizado en Q4_K_M, aproximadamente 4 bits por parámetro, y ocupa unos 4,68 GiB.
CPU
Primero probé el modelo utilizando únicamente la CPU y variando el número de hilos:
| Hilos | pp512 | tg128 |
|---|---|---|
| 4 | 45,13 t/s | 5,49 t/s |
| 8 | 66,70 t/s | 5,57 t/s |
| 12 | 68,93 t/s | 5,57 t/s |
| 16 | 54,34 t/s | 2,22 t/s |
El Ryzen 7 8745H tiene 8 núcleos físicos y 16 hilos, pero, como se observa en los resultados, utilizar los 16 hilos no mejora el rendimiento. De hecho, tanto en el procesamiento del prompt como en la generación de tokens queda por debajo de las configuraciones con 8 y 12 hilos, y en tg128 llega incluso a rendir peor que con 4.
Esto se debe a que esos 16 hilos no equivalen a 16 núcleos independientes. Los hilos lógicos comparten recursos dentro de cada núcleo físico y, en una carga como esta, llega un punto en el que añadir más hilos aumenta la competencia por la caché, el ancho de banda de memoria y otros recursos internos.
Vulkan y GPU
Para utilizar la Radeon 780M integrada instalé el soporte necesario para Vulkan y utilicé la compilación build-gpu creada antes. Como el usuario llm ejecuta el proceso, también fue necesario darle acceso al dispositivo de renderizado:
$ sudo adduser llm render
La diferencia práctica entre los benchmarks de CPU y GPU queda reflejada directamente en los comandos:
# CPU: probar 4, 8, 12 y 16 hilos
$ ./build/bin/llama-bench \
-m /srv/llm/models/Qwen3-8B-Q4_K_M.gguf \
-t 4,8,12,16 > ../cpu.txt
# GPU: descargar a la Radeon tantas capas como sea posible con -ngl 99
$ ./build-vulkan/bin/llama-bench \
-m /srv/llm/models/Qwen3-8B-Q4_K_M.gguf \
-ngl 99 > ../gpu.txt
En CPU interesa variar el número de hilos. En GPU deja de ser una variable importante para esta comparación, porque el trabajo se descarga a la Radeon.
Los resultados fueron:
| Prueba | CPU | Radeon 780M |
|---|---|---|
pp512 | 68,93 t/s | 231,59 t/s |
tg128 | 5,57 t/s | 8,21 t/s |
La diferencia es especialmente grande al procesar el prompt: la GPU es aproximadamente 3,4 veces más rápida. En generación de texto la mejora es menor, alrededor de 1,5 veces.
Qwen3 14B Q4_K_m
Este modelo tiene unos 14,77 mil millones de parámetros, también cuantizado en Q4_K_M, y ocupa aproximadamente 8,38 GiB. El 14B contiene alrededor de 1,8 veces más parámetros que el 8B. En principio puede ofrecer mayor capacidad, pero para generar cada token tiene que mover y procesar una cantidad de datos considerablemente mayor.
CPU
| Hilos | pp512 | tg128 |
|---|---|---|
| 4 | 23,11 t/s | 3,01 t/s |
| 8 | 36,00 t/s | 3,06 t/s |
| 12 | 36,26 t/s | 3,07 t/s |
| 16 | 33,31 t/s | 1,54 t/s |
Se repite el comportamiento del 8B. El mejor resultado aparece antes de llegar a los 16 hilos y la generación cae especialmente cuando se utilizan todos los hilos lógicos.
GPU
Con la Radeon 780M y Vulkan:
pp512 | tg128 |
|---|---|
| 127,21 t/s | 4,33 t/s |
Comparando directamente los dos tamaños:
| Modelo | Tamaño | Backend | pp512 | tg128 |
|---|---|---|---|---|
| Qwen3 8B Q4_K_M | 4,68 GiB | CPU | 68,93 t/s | 5,57 t/s |
| ’’ | 4,68 GiB | Radeon 780M | 231,59 t/s | 8,21 t/s |
| Qwen3 14B Q4_K_M | 8,38 GiB | CPU | 36,26 t/s | 3,07 t/s |
| ’’ | 8,38 GiB | Radeon 780M | 127,21 t/s | 4,33 t/s |
El modelo de 14B funciona sin problemas en el Mini PC, pero genera texto aproximadamente a la mitad de velocidad que el 8B. Con Vulkan, tg128 pasa de 8,21 t/s a 4,33 t/s.
Esto muestra de forma bastante clara el intercambio entre ambos tamaños: el 8B es más rápido, mientras que el 14B sacrifica velocidad a cambio de utilizar un modelo con mayor capacidad.
Qwen3 8B Q8_0
Hasta aquí había comparado dos modelos con la misma cuantización Q4_K_M: uno de 8B y otro de 14B. La siguiente prueba cambia una sola cosa: vuelvo al modelo de 8,19 mil millones de parámetros, pero utilizo una cuantización de 8 bits, Q8_0. El modelo ocupa 8,11 GiB, casi lo mismo que el Qwen3 14B Q4_K_M. Esta comparación de dos modelos que utilizan aproximadamente la misma cantidad de memoria nos permitirá comprobar si para las pruebas resulta mejor tener menos parámetros pero mayor precisión o más parámetros con una cuantización más agresiva.
CPU
| Hilos | pp512 | tg128 |
|---|---|---|
| 4 | 37,69 t/s | 3,17 t/s |
| 8 | 55,02 t/s | 3,25 t/s |
| 12 | 49,40 t/s | 3,25 t/s |
| 16 | 45,81 t/s | 1,16 t/s |
GPU
pp512 | tg128 |
|---|---|
| 263,47 t/s | 4,49 t/s |
Aquí está la comparación entre los tres modelos usando la Radeon:
| Modelo | Tamaño | Params | Quant | pp512 | tg128 |
|---|---|---|---|---|---|
| Qwen3 8B Q4_K_M | 4,68 GiB | 8,19 B | ~4 bits | 231,59 t/s | 8,21 t/s |
| Qwen3 8B Q8_0 | 8,11 GiB | 8,19 B | 8 bits | 263,47 t/s | 4,49 t/s |
| Qwen3 14B Q4_K_M | 8,38 GiB | 14,77 B | ~4 bits | 127,21 t/s | 4,33 t/s |
El 8B Q8_0 procesa el prompt más rápido que el 8B Q4_K_M, pero genera texto bastante más despacio. En velocidad de generación, el 8B Q8_0 y el 14B Q4_K_M quedan prácticamente empatados.
La comparación de rendimiento no dice por sí sola cuál es el mejor modelo. Precisamente el siguiente paso es comprobar si la mayor precisión de un 8B Q8_0 compensa tener muchos menos parámetros que un 14B Q4_K_M, o si para una cantidad similar de memoria resulta preferible dedicar ese espacio a un modelo más grande aunque esté más cuantizado.
Memoria y cuello de botella
Durante estas pruebas, los 32 GB de RAM no causaron problemas. Mientras se ejecutaba el benchmark con la Radeon, el sistema seguía mostrando alrededor de 17 GiB de memoria disponible. Con estos modelos el límite actual no es la capacidad de memoria, sino su ancho de banda.
La Radeon 780M es una GPU integrada y no dispone de una gran memoria VRAM dedicada, por lo que CPU y GPU acceden a la misma DDR5 del sistema. Durante la generación de cada token hay que leer una gran cantidad de los pesos del modelo desde esa memoria. Al pasar de un archivo de 4,68 GiB en el 8B a 8,38 GiB en el 14B, aumenta aproximadamente en la misma proporción la cantidad de información que debe recorrerse, mientras que el ancho de banda disponible no cambia.
Los resultados reflejan este comportamiento de forma bastante clara: con la Radeon, el 14B conserva aproximadamente la mitad de la velocidad de generación del 8B.
Así, por ahora pueden distinguirse dos límites diferentes. El límite físico de memoria todavía está lejos: ambos modelos caben con holgura. El que empieza a aparecer es el límite práctico de rendimiento. Qwen3 8B genera a unos 8,2 t/s con Vulkan, mientras que Qwen3 14B baja a unos 4,3 t/s.
Para próximas entregas relacionadas con la IA profundizaré más en casos de uso prácticos.