Execució de LLM amb vGPU NVIDIA¶
Cas d'ús¶
Objectiu: executar un LLM (Large Language Model) en un escriptori virtual amb una NVIDIA vGPU. Volem provar a escriure i executar codi que interactui amb el model, i muntar un servei de chat vía web.
Context:¶
Un LLM (Model de Llenguatge de Gran Escala) és un model d'intel·ligència artificial basat en xarxes neuronals profundes, dissenyat per processar i generar text de manera similar a com ho fan els humans. Aquests models s'entrenen amb grans quantitats de dades textuals, cosa que els permet comprendre el context, respondre preguntes i crear contingut amb una qualitat notable. Són eines potents que poden adaptar-se a diverses tasques, com ara la traducció, la redacció o l'anàlisi de textos, i són la base de moltes aplicacions modernes d'IA.
Ollama és una eina de codi obert que facilita l'execució de LLMs en dispositius locals, cosa que permet als usuaris treure profit de models avançats sense haver de dependre de serveis al núvol. Això significa que pots tenir un model com DeepSeek, conegut per la seva eficiència i capacitat multilingüe, funcionant directament al teu ordinador. Això ofereix un control més gran sobre el model i les dades que processa, a més de fer-ho accessible en entorns sense connexió a internet.
Utilitzar aquests models localment ofereix avantatges com una major privadesa, ja que les dades no surten del teu dispositiu, i elimina els costos associats als serveis al núvol. Per exemple, amb DeepSeek executat localment a través d'Ollama, un usuari podria personalitzar-lo per a tasques especialitzades, com l'anàlisi tècnica o la generació de contingut en un idioma concret, com el català, tot des del seu propi equip. Aquesta autonomia i flexibilitat fan que sigui una opció molt valuosa per a usuaris individuals o organitzacions amb necessitats específiques.
Crear escriptori amb GPU¶
Sistema operatiu base: Ubuntu 22.04
Seguirem els següents passos:
1. Crearem un escriptori amb Sistema Operatiu Ubuntu. (Manual per crear escriptori Ubuntu 22.04: https://isard.gitlab.io/isardvdi-docs/guests/ubuntu_22.04/desktop/installation/installation.ca/)
-
Li donarem el perfil de la GPU que tenim disponible a la infraestructura d'Isard.
-
Deixarem la targeta de vídeo "Default"
Actualització del sistema operatiu¶
sudo apt update
sudo apt upgrade -y
Passos previs per fer servir NVIDIA amb docker i per còmput¶
Seleccionar NVIDIA solament per còmput.¶
És important que la targeta vGPU de NVIDIA no es configuri com el dispositiu gràfic principal del sistema. Si la vGPU s'encarrega de renderitzar l'entorn gràfic, consumirà recursos que haurien de destinar-se a la seva funció principal: el processament de dades. Això afecta l'eficiència i el rendiment en tasques de càlcul intensiu. Per això, és recomanable assignar una GPU secundària per a la gestió gràfica i reservar la vGPU exclusivament per al processament de dades.
La targeta de vídeo "default" en realitat és la QXL, li diem a xorg que faci servir aquesta targeta.
isard@ubuntu22:~$ cat /etc/X11/xorg.conf.d/10-qxl.conf
Section "Device"
Identifier "QXL"
Driver "qxl"
BusID "PCI:0:1:0" # Ajusta això segons la sortida de lspci per QXL
EndSection
Section "Screen"
Identifier "Screen0"
Device "QXL"
EndSection
Amb QXL ens interessa que no arranqui wayland amb el gestor d'inici de sessió gdm3, cal validar que tenim:
# GDM configuration storage
#
# See /usr/share/gdm/gdm.schemas for a list of available options.
[daemon]
AutomaticLoginEnable=true
AutomaticLogin=isard
WaylandEnable=false
Instal·lar drivers correctes de NVIDIA¶
Hem de tenir els drivers acords a la versió del mòdul de kernel del servidor. El més adient és instal·lar la versió Long-Term Support (v16 - R535)
vGPU Software Release | Driver Branch | vGPU Branch Type | Latest Release in Branch | Release Date | EOL Date |
---|---|---|---|---|---|
NVIDIA vGPU 18 | R570 | Production | 18.0 | March 2025 | March 2026 |
NVIDIA vGPU 17 | R550 | Production | 17.5 | January 2025 | June 2025 |
NVIDIA vGPU 16 | R535 | Long-Term Support | 16.9 | January 2025 | July 2026 |
-
Manuals per poder realitzar la instal·lació correcta dels drivers i el token.
-
Instal·lació dels drivers: https://isard.gitlab.io/isardvdi-docs/user/gpu.ca/#installacio
-
Instal·lació del token: https://isard.gitlab.io/isardvdi-docs/user/gpu.ca/#gestio-del-token
-
sudo cp /media/isard/nvidia/nvidia_16/Guest_Drivers/nvidia-linux-grid-535_535.230.02_amd64.deb /opt/
sudo apt install /opt/nvidia-linux-grid-535_535.230.02_amd64.deb -y
reboot
Verifiquem amb nvidia-smi que es detecta el driver i la versió de CUDA:
isard@ubuntu22:~$ nvidia-smi
Mon Mar 10 17:23:13 2025
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.230.02 Driver Version: 535.230.02 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA A16-4Q On | 00000000:06:00.0 Off | 0 |
| N/A N/A P0 N/A / N/A | 57MiB / 4096MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 1263 C+G ...libexec/gnome-remote-desktop-daemon 57MiB |
+---------------------------------------------------------------------------------------+
Hi ha un process "gnome-remote-desktop-daemon" que és per l'accés rdp, i que no hauria de fer servir la NVIDIA. És un bug i de moment no hem pogut evitar-ho.
Llicenciament NVIDIA¶
Cal afegir llicència de NVIDIA modificant FeatureType a gridd.conf:
isard@ubuntu22:/opt/llm$ sudo grep FeatureType /etc/nvidia/gridd.conf
FeatureType=1
I afegir fitxer de token al directori ClientConfigToken:
isard@ubuntu22:/opt/llm$ sudo ls -lh /etc/nvidia/ClientConfigToken/
total 4,0K
-rw-r--r-- 1 root root 2,7K mar 10 18:30 token2.tok
Reinici del servei de llicenciament:
sudo systemctl restart nvidia-gridd.service
Verificar que està llicenciada amb nvidia-smi -q:
isard@ubuntu22:/opt/llm$ nvidia-smi -q |grep "License Status"
License Status : Licensed (Expiry: 2025-3-11 17:31:20 GMT)
Es reinicia i verifiquem que fa servir la qxl amb aquesta ordre:
sudo apt install mesa-utils -y
glxinfo |grep -i nvidia
No ha de sortir cap línia de NVIDIA.
Install docker¶
https://docs.docker.com/engine/install/ubuntu/
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo docker run hello-world
Afegir a docker que pugui fer servir gpus:¶
Ens cal nvidia-container-toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
Verifiquem que ha modificat el fitxer de configuració:
isard@ubuntu22:~$ cat /etc/docker/daemon.json
{
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
Ara restart del servei de docker i verificar que nvidia-smi funciona i accepta i reconeix les gpus:
sudo systemctl restart docker
sudo docker run --rm --gpus all nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi
Docker compose¶
mkdir /opt/llm
cd /opt/llm
Crear fitxer docker-compose.yml:
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
ports:
- "11434:11434"
volumes:
- /opt/ollama/volume_ollama:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
environment:
- OLLAMA_HOST=0.0.0.0:11434
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-WebUI
ports:
- "3000:8080"
volumes:
- /opt/ollama/openwebui_backend_data:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
extra_hosts:
- "host.docker.internal:host-gateway"
restart: always
Arrencar docker compose:
docker compose up -d
Run del model:
Model | Requisits | Comanda |
---|---|---|
1.5B Paràmetres | 1.1 GB aprox. | ollama run deepseek-r1:1.5b |
7B Paràmetres | 4.7 GB aprox. | ollama run deepseek-r1 |
70B Paràmetres | +20 GB de vRAM | ollama run deepseek-r1:70b |
671B Paràmetres | +300 GB de vRAM | ollama run deepseek-r1:671b |
sudo docker exec -ti ollama ollama run deepseek-r1:1.5b
A un navegador intriduïm la següent adreça: http://localhost:3000
Exemple de codi amb python¶
sudo apt install python3-virtualenv -y
mkdir -p dev/llm_python
cd dev/llm_python
virtualenv venv
source venv/bin/activate
Dins del venv:
pip3 install ipython openai
ipython3
codi python, fem copy/paste:
import openai
# Conectar-se a Ollama
client = openai.Client(
base_url="http://localhost:11434/v1",
api_key="ollama"
)
response = client.chat.completions.create(
model="deepseek-r1", # Canviem 1.5b per la versió instal·lada
messages=[{"role": "user", "content": "Hellow in catalan"}],
temperature=0.7
)
print(response.choices[0].message.content)