Ejecutando Ollama con GPU en un miniPC AMD (ROCm vs Vulkan)

Ejecutando Ollama con GPU en un miniPC AMD (ROCm vs Vulkan)

Hace poco tiempo me hice de un miniPC con un Ryzen moderno y una iGPU bastante potente (AMD Radeon 780M), pensé algo muy simple:

"Perfecto. Esto debería correr modelos locales con Ollama usando GPU."

Y sí… eventualmente lo logré, pero el camino no fue solamente hacer "docker compose up y listo".

Fue más bien una historia de:

  • empezar en CPU,
  • intentar ROCm porque AMD,
  • ver que todo se caía silenciosamente a CPU,
  • descubrir Vulkan,
  • pelear con permisos,
  • probar con radeontop,
  • cambiar una sola línea (:rocm:latest)
  • y finalmente ver esto:
PROCESSOR 100% GPU

Este post es exactamente ese recorrido, con comandos reales, salidas reales y errores reales.

Todo empezó con lo básico: “¿Ollama está vivo?”

Primero levanté Ollama dentro de Docker, nada fancy, solo asegurarme de que respondía.

Lo primero que siempre hago:

curl -s http://localhost:11434/api/tags | head

y la salida (con mi cara de, funciono a la primera)

{"models":[]}

Eso era buena señal, no había modelos descargados todavía, pero el servidor estaba arriba.

Descargando un modelo pequeño: primer éxito en CPU

Descargué algo ligero, porque mi objetivo no era chat, sino pipelines para generar:

  • keywords
  • taxonomy
  • summaries
  • takeaways

Así que empecé con:

docker exec -it ollama ollama pull llama3.2:3b

Luego probé:

docker exec -it ollama ollama run llama3.2:3b \
"Return JSON with: keywords (5), tldr (1 sentence). Topic: Deeditt journaling."

Y respondió perfecto, entonces en ese momento pensé:

"Ok.. funciona. y como hago el switch para usar el GPU."

La primera verdad incómoda: estaba en CPU

Lo confirmé con:

docker exec -it ollama ollama ps

Y vi esto:

NAME           SIZE      PROCESSOR    CONTEXT
llama3.2:3b    3.9 GB    100% CPU     4096

Pues creí que automaticamente ollama usaría por si mismo sin configuraciones extras el GPU y ahí empezó la verdadera historia.

Intento natural: “AMD = ROCm, ¿no?”

Y como estoy trabajando con AMD, lo lógico era pensar:

“Necesito ROCm.”

Si, ya había leído algo sobre ROCm, pues es para AMD lo que CUDA es para NVidia, entonces investigué y si, hay una version de ollama con rocm, cambié la imagen y probé:

image: ollama/ollama:rocm

Le pasé dispositivos de mi host al contenedor segun las instrucciones y a probar.

devices:
  - /dev/kfd
  - /dev/dri

Y sí.. Ollama seguía funcionando, pero el problema era más silencioso.. Todo seguía cayendo a CPU, honestamente estaba un poco perdido, asi que gasté un par de hrs más tratando de leer y entender como funciona.

El caso clásico con la Radeon 780M (gfx1103)

Aquí hay algo importante que aprendí:

La Radeon 780M usa arquitectura

gfx1103

En AMD, el código de nombre "gfx" se utiliza para identificar las diferentes arquitecturas de sus procesadores gráficos. En este caso, gfx1103 es el código de nombre específico para la arquitectura utilizada en la Radeon 780M.

La notación gfx1103 se puede desglosar de la siguiente manera:

  • gfx: Prefijo que indica que se trata de una arquitectura de procesador gráfico de AMD.
  • 11: Indica la generación de la arquitectura (en este caso, la undécima generación).
  • 03: Especifica la variante o revisión específica de la arquitectura.

Por lo tanto, gfx1103 se refiere a la arquitectura específica utilizada en la Radeon 780M, que se basa en la arquitectura RDNA 3 de AMD.

  • Arquitectura: RDNA 3
  • Código de nombre: GFX1103
  • Número de núcleos: 12 núcleos RDNA 3
  • Velocidad de reloj: Hasta 2,9 GHz
  • Memoria: Hasta 16 GB de memoria GDDR6
  • Interfaz de memoria: 128 bits

Básicamente la Radeon 780M ofrece un rendimiento gráfico decente para juegos y aplicaciones de entretenimiento, incluyendo soporte para tecnologías como DirectX 12, Vulkan y OpenGL 4.6.

ROCm está mejorando, pero todavía es inconsistente dependiendo de:

  • kernel
  • versión ROCm
  • distro
  • builds de contenedor

Lo peor es que ROCm puede fallar sin decir nada .. ahh entonces Ollama simplemente hace fallback:

"Ok, regreso a CPU entonces"

Por eso la herramienta más honesta no es un log, digamos que para esta etapa lo mejor era utilizar herramientas de radeon y encontré esto:

radeontop

Al ejecutarlo, cualquier señal de uso de GPU, lo notaría y si está en 0%, no hay magia, mi cacharro seguiría sin funcionar.

Cuando vi que GPU estaba en 0%, supe que algo estaba mal

Corría modelos, pero:

Graphics pipe 0.00%
GPU 0%

Entonces empecé a sospechar, igual estaba en un punto de o sigo intentando con el contenedor o me muevo a una instalacion nativa en el host.

"Quizá el contenedor ni siquiera tiene soporte GPU real, porque no fue compilado para ello"

Y ahí vino el comando clave.

Revisando los logs del backend: ¿esta versión de Ollama tiene soporte para GPU?

Dentro del contenedor:

docker exec -it ollama bash -lc \
"ls -1 /usr/lib/ollama/libggml-* | head"

Y solo vi:

libggml-cpu-icelake.so
libggml-cpu-haswell.so
...

Y lo que estaba buscando era algún indicio de vulkan o rocm, basicamente no vi nada como:

  • libggml-rocm
  • libggml-hip
  • libggml-vulkan

Cambio de dirección: Vulkan en lugar de ROCm

Así es, me cansé de intentarlo y de no tener una dirección clara, entonces fue cuando la conversación cambió completamente:

AMD iGPU + Ollama funciona mejor con Vulkan que con ROCm.

Así que decidí probar Vulkan, que también ya había leído un poco, pero que es Vulkan entonces? de acuerdo a la documentación: Vulkan es una API de gráficos de bajo nivel que proporciona una forma más eficiente y flexible de interactuar con el hardware de gráficos de una computadora. Está diseñada para ser más eficiente que las APIs de gráficos tradicionales, como OpenGL y DirectX, y para proporcionar una mayor flexibilidad y control sobre el hardware de gráficos.

  • Vulkan y ROCm juntos: Sin embargo, Vulkan y ROCm pueden coexistir y complementarse entre sí. Por ejemplo, una aplicación que utilice Vulkan para interactuar con el hardware de gráficos puede utilizar ROCm para aprovechar el poder de cómputo de las tarjetas gráficas Radeon.

En resumen, Vulkan y ROCm son dos tecnologías diferentes que se enfocan en aspectos diferentes del desarrollo de aplicaciones. Vulkan es una API de gráficos de bajo nivel que proporciona un acceso directo al hardware de gráficos, mientras que ROCm es una plataforma de cómputo que permite a los desarrolladores crear aplicaciones de cómputo de alto rendimiento.

Dejemos la teoría y sigamos...

Primero: Vulkan en el host, pero falló por permisos

Instalé Vulkan:

sudo apt install mesa-vulkan-drivers vulkan-tools

y probé que estuviera disponible y funcionando en mi máquina:

vulkaninfo --summary | head

Y me salió esto, que vaya, parece que funciona, pero no tengo los permisos correctos.

Could not open device /dev/dri/renderD128: Permission denied

Ya sé, ese fue un momento clásico Linux:

"Sí, está instalado… pero no tienes permisos"

El fix real: permisos para renderD128

El grupo render es un grupo especial en Linux que se utiliza para controlar el acceso a dispositivos de renderizado de gráficos, como tarjetas gráficas y dispositivos de salida de video. Los miembros del grupo render tienen permiso para acceder a estos dispositivos y utilizarlos para renderizar gráficos.

El grupo video es otro grupo especial en Linux que se utiliza para controlar el acceso a dispositivos de video, como cámaras web, tarjetas de captura de video y otros dispositivos de video. Los miembros del grupo video tienen permiso para acceder a estos dispositivos y utilizarlos para capturar y procesar video.

Entonces puse a mi usuario como parte de estos grupos.

sudo usermod -aG render,video $USER

Luego hice un logout/login en mi sistema para persistir los cambios y no tener más problemas e intenté confirmar que todo estuviera bien.

groups
ls -l /dev/dri/renderD128

Y ahora, si todo estaba en orden, debería ver algo con más sentido con el siguiente comando:

vulkaninfo --summary | head -n 40

Y que creen, salida hermosa .. ahí estaba lo que quería ver, finalmente parecía que iba en la dirección correcta.

deviceName = AMD Radeon 780M Graphics (RADV PHOENIX)
driverName = radv
Mesa 25.x.x

Vulkan estaba funcionando, pero ¿Qué hay en el grupo render y video que arregló el problema?

Al agregar el usuario actual al grupo render y video, se le otorgó permiso para acceder al dispositivo /dev/dri/renderD128, que es un dispositivo de renderizado de gráficos utilizado por Vulkan.

En particular, el grupo render tiene permiso para acceder a los dispositivos de renderizado de gráficos, como /dev/dri/renderD128, que es el dispositivo utilizado por Vulkan para renderizar gráficos en la tarjeta gráfica AMD Radeon 780M Graphics.

Nada de esto me lo inventé, ni lo sé de memoria, pasé leyendo toda la noche para entenderlo y aplicarlo.

Ahora sí: Vulkan dentro del contenedor

Cambié el compose hacia esto (ojo, ya no estoy usando ollama:rocm como imagen)

image: ollama/ollama:latest
devices:
  - /dev/kfd
  - /dev/dri
environment:
  OLLAMA_VULKAN: "1"
  OLLAMA_NUM_PARALLEL: 4
  OLLAMA_MAX_LOADED_MODELS: 2
  OLLAMA_KEEP_ALIVE: 24h

Y una vez re-deployando el contenedor, lo que buscaba era ver dentro del contenedor a OLLAMA VULKAN con una salida 1.

docker exec -it ollama bash -lc "echo $OLLAMA_VULKAN"

La variable de entorno OLLAMA_VULKAN se utiliza en la imagen de Docker de OLLAMA para habilitar el soporte de Vulkan para la generación de imágenes, y si, es una prueba simple, pero creí que si confirmaba que VULKAN estaba activo, ya podría ejecutar el comando ldconfig -p | grep -i vulkan | head

Entonces todo junto quedaría como:

docker exec -it ollama bash -lc \
"ldconfig -p | grep -i vulkan | head"

Y claro, ya usando la imagen correcta, la salida parecía más cercano a lo que esperaba:

libvulkan_radeon.so
libvulkan.so.1
...

El momento final: correr modelos y ver el uso del GPU con radeontop

Hasta ahora solo había confirmado que vulkan estaba activo, pero la prueba real era probando un modelo pequeño, por ej. 8B:

docker exec -it ollama ollama run llama3:8b-instruct-q4_K_M \
"Write 10 bullet takeaways about digital distraction."

Mientras veía los logs del contenedor, y finalmente apareció desde Docker (ni siquiera tuve que revisar radeontop), honestamente no sabía que Docker tenía esta salida.

NAME                         SIZE      PROCESSOR    CONTEXT
llama3:8b-instruct-q4_K_M    7.9 GB    100% GPU     4096

Y claro, luego revisé radeontop y ahí estaba la confirmación de que el GPU ya estaba siendo usado, pues se dispararon brevemente los indicadores de uso y fue ese el verdadero "esta vivo".

Lo que aprendí (y lo que te ahorra horas)Ñ

  • Ollama puede correr en GPU en AMD iGPU.
  • ROCm no es siempre el camino correcto, quizás en algunos meses este listo, pero no quiero volver a probarlo a menos que tenga real necesidad y un mejor hardware.
  • Vulkan + Mesa es más estable en miniPCs modernos
  • radeontop es el detector definitivo para este tipo de setup.

La prueba fue entretenida al igual que escribir esta artículo, finalmente todo funciona y ollama esta en ejecución, trabajando como debería y aunque no es tan rápido como imaginaba, es bastante decente a la vez que mantengo mi información privada de los modelos de LLM, que aunque son rápidos y eficientes, para tareas como lo que necesito en este momento, prefiero local.

Happy coding :)


Photo by Oleksandr Sushko on Unsplash

Written with StackEdit.

Jack Fiallos

Jack Fiallos

Te gustó este artículo?