Costruire una workstation AI locale: 2 RTX 3060, CUDA, Unsloth e tutti gli errori che ho fatto

In questo articolo voglio raccontarvi di un viaggio. Un percorso tortuoso, immerso nei meandri dell’intelligenza artificiale “casalinga”, in locale.

Tutto ha avuto inizio quando ho assemblato per la prima volta un computer per cominciare a “giocare” con l’AI casereccia. Andiamo indietro di circa un anno, ovvero al video del 30 settembre ’25 intitolato “ChatGPT crea un computer per se stesso”. Da quel giorno è stato un susseguirsi di esperimenti, fatti anche con i vari mini PC recensiti, come Mllse e Soayan.

Successivamente al video con Ollama compilato per la NVIDIA Tesla K80, del 24 maggio ’26, mi sono ritrovato tra le mani una scheda madre vecchia, ma ancora ottima per questo tipo di utilizzo. La ASUS X99 Deluxe ha un pedigree favoloso per mettere in piedi una workstation con ancora molte carte da giocare: 8 slot per DDR4, socket 2011-3 per CPU con un’infinità di core e thread e 5 slot PCI Express, di cui il primo e il terzo elettricamente connessi a 16 linee, quindi a piena banda e ottimi per quello che avevo in mente. Ho disassemblato il primo computer che ospitava la RTX 3060 da 12 GB e al suo posto ho messo una RTX 2060 Super da 8 GB. Ed è ancora così, con la sua mainboard cinese, lo Xeon E5-2680 v3, 32 GB di DDR4 e un NVMe da 256 GB. Funziona alla grande e, con LMDE7, è un ottimo muletto.

Ma torniamo in tema, alla build con la ASUS X99 Deluxe, che nel frattempo ha visto un discreto restyling.

Ho sostituito lo Xeon E5-2698 v3 in favore di un E5-1650 v4. Il primo ha sì 16 core e 32 thread, ma una frequenza base di 2,3 GHz, mentre l’altro ha meno core, 6C/12T, ma una frequenza base di 3,6 GHz. Ottengo così un sistema più reattivo e performante, considerando che, per l’uso che ne dovrò fare, di tutti quei core non me ne faccio praticamente niente. Oltre alla CPU ho aggiunto… anzi, ho tolto i quattro banchi di DDR4 “normale” e messo otto banchi di DDR4 ECC unbuffered, per un totale di 64 GB di RAM. Ho anche messo l’NVMe da 1 TB che avevo in casa disoccupato come disco principale di boot. Ha ottime prestazioni, considerando l’età della scheda madre. Il componente più succoso aggiunto è però una seconda GPU identica alla prima, ovvero una Gigabyte RTX 3060 OC da 12 GB. L’aggiunta della seconda GPU non fa magicamente diventare il sistema una macchina con 24 GB di VRAM.

Cioè, sì, ma anche no.

Mi spiego allacciandomi alla metafora usata nel video: non ho un serbatoio di benzina da 24 litri, ma due serbatoi separati da 12. Questi rimangono comunque distinti e, quando un carico viene distribuito tra le due schede, dati e sincronizzazione devono comunque transitare attraverso il resto del sistema. Ecco perché, durante alcuni carichi che coinvolgono entrambe le GPU, tramite una qualsiasi utility di monitoraggio (Btop, Htop) vedo anche la CPU lavorare parecchio. Nel video, a un certo punto, si vede circa il 300%, ovvero tre core a manetta.

Una GPU come la RTX 3090 da 24 GB non deve gestire la memoria suddivisa tra due schede e, a parità di altre condizioni, le inferenze AI saranno sicuramente più veloci. Oltre al fatto che la 3090 dispone di una banda passante della memoria enormemente superiore. Ma questo, qui, è quasi secondario: sto parlando soprattutto della differenza tra VRAM suddivisa e VRAM contigua.

A questo punto la workstation è finita. Per tutto l’hardware installato ho fatto un video specifico, che trovate a questo link.

LMDE 7, due RTX 3060 e il primo problema

Installo Linux Mint Debian Edition 7 “Gigi”, LMDE 7: per me il miglior sistema operativo esistente sulla faccia della Terra. E qui ci sarebbe da scrivere un articolo a parte che magari, tempo permettendo, un giorno farò.

A installazione terminata iniziano i primi problemi. LightDM, il display manager, ovvero quella parte del sistema che presenta la schermata nella quale si inseriscono nome utente e password, non parte. Il sistema rimane con il cursore lampeggiante ma, dopo aver effettuato il login dalla console e aver scritto nel terminale:

startx

X11 si avvia regolarmente e con esso il desktop environment Cinnamon.

Perché?

Ci sono volute un paio d’ore per capire il problema. LightDM tentava di partire prima che la GPU scelta e lo stack grafico fossero completamente pronti. Una classica “race condition”, insomma.

È bastato, si fa per dire, indicare esplicitamente a Xorg quale delle due GPU utilizzare come primaria, creando il file:

/etc/X11/xorg.conf.d/10-primary-gpu.conf

con queste righe:

Section "Device"
    Identifier "PrimaryGPU"
    Driver "nvidia"
    BusID "PCI:1:0:0"
EndSection

In questo modo Xorg sapeva che la scheda da utilizzare per l’ambiente grafico era quella collegata al bus PCI 01:00.0.

Non era però ancora sufficiente. Ho dovuto anche ritardare di qualche secondo l’avvio di LightDM, creando un override systemd nel file:

/etc/systemd/system/lightdm.service.d/override.conf

contenente:

[Service]
ExecStartPre=/bin/sleep 5

Inizialmente avevo provato con 3 secondi, poi portati a 5. Quel piccolo ritardo dava al driver NVIDIA e a Xorg il tempo necessario per inizializzarsi correttamente prima dell’avvio del display manager e dopo un:

sudo systemctl daemon-reload

e il successivo riavvio, LightDM ha finalmente iniziato ad avviarsi regolarmente.

Risolto questo intoppo, ho potuto installare i driver NVIDIA della serie 550.xxx e qui ho commesso un errore banale, ma significativo per quello che sarebbe accaduto successivamente. Il secondo errore è stato installare il CUDA Toolkit 12.4 “bare metal”, ovvero scaricare il pacchetto .run da oltre 4 GB dal sito NVIDIA e avviare la procedura di installazione direttamente su Linux, accanto ai driver.

Perché i driver 550 e CUDA 12.4?

Cercherò di spiegarlo in modo semplice. Le GPU NVIDIA, oltre al numero del modello, come 1080, 1650, 2070 ecc., appartengono a diverse famiglie architetturali. Abbiamo, in ordine cronologico, Kepler, Maxwell, Pascal, Turing, Ampere, Ada Lovelace e, più recentemente, Blackwell. Le mie RTX 3060 appartengono alla famiglia Ampere. Ogni generazione ha un certo intervallo di driver utilizzabili e ogni ramo dei driver determina anche quali versioni CUDA può supportare. Per esempio, il ramo 510 arriva a CUDA 11.6, mentre i 550 che avevo installato arrivavano al supporto CUDA 12.4. In pratica driver e CUDA devono convivere entro determinate regole. Non posso semplicemente prendere qualsiasi versione dell’uno e abbinarla a qualsiasi versione dell’altro sperando che tutto funzioni. Il modo di forzare certe situazioni esiste, ma lasciamolo perdere perché si entra rapidamente in un delirio di compatibilità che non serve allo scopo di questo articolo.

Facciamo un esempio pratico. Ho un computer con una Tesla K80. Quella scheda, appartenente alla generazione Kepler, è ormai limitata a driver e versioni CUDA abbastanza vecchi. Se voglio utilizzare un’applicazione moderna che richiede una versione CUDA più recente di quella disponibile per quella GPU, sono fregato. O cambio hardware, scelta generalmente sensata, oppure devo trovare una versione del software adattata appositamente a quell’ambiente. È quello che ho fatto con Ollama e la Tesla K80: non ho ricompilato personalmente il software, magari ne fossi capace, ma ho utilizzato Ollama37, il fork realizzato da dogkeeper886 proprio per mantenere il supporto alle GPU NVIDIA con compute capability 3.7 come, appunto, la K80. Il progetto utilizza una toolchain compatibile con Kepler e permette quindi di eseguire Ollama su hardware che il progetto originale ha ormai abbandonato. In quest’ultimo caso serve sapere molto bene quello che si sta facendo: compilatori, librerie, dipendenze, CUDA e tutti i santi che stanno dietro hardware e software.

Meglio cambiare computer, fidatevi.

Ma torniamo al mio caso. Secondo voi quali driver ho scelto per le mie RTX 3060?

Quelli di mezzo: i 550.

Sbagliando, ma ancora non lo sapevo.

Poi, come ho già detto, ho installato CUDA 12.4 “bare metal”.

Sbagliando di nuovo.

Il sistema configurato in questo modo funzionava perfettamente. Quindi, direte voi, perché continuo a dire di aver sbagliato? Ollama andava che era un piacere, Open WebUI funzionava e ComfyUI funzionava. Nessun errore. I vari compiti AI impartiti ai software venivano eseguiti esattamente come ci si aspetterebbe da un sistema ben configurato. Ma c’era il trucco: i virtual environment, i famigerati venv. Questi però ve li spiegherò tra poco, perché prima c’è ancora qualcosa da raccontare.

Arriva Unsloth e comincia il divertimento

Nella mia passione da content creator (mado’ che parolone), spesso mi servono immagini da sovrapporre ai video. Immagini che definisco “spicce”, veloci insomma, non generate con ComfyUI attraverso un serpaio di spaghetti colorati capace di far impallidire chiunque. Roba da scrivere un prompt, cliccare “Genera” e ottenere il risultato. È qui che entra in gioco Unsloth Studio, una piattaforma piuttosto completa per lavorare in locale con LLM, immagini, audio, testo e altre tipologie di modelli, con in più la possibilità di fare fine-tuning e addestramento.

Mi collego quindi al sito di Unsloth, copio la riga di comando per installarlo da terminale e…

SBAM!

Decine di righe rosse di errori su errori, quasi tutti riconducibili a incompatibilità tra la versione CUDA supportata dal sistema e le librerie PyTorch che Unsloth stava tentando di installare. Ma dico: se Ollama, Open WebUI e ComfyUI funzionano, perché Unsloth no? Cos’ha questo in più, o in meno, rispetto agli altri? Mi sono messo a fare ricerche sul web partendo più o meno da cinque parole: “Errore installazione Unsloth CUDA 12”. Da lì non saprei neanche dire quanto tempo sia passato, forse tutto il pomeriggio. Ero talmente concentrato da aver perso completamente la cognizione del tempo. Inizialmente ero convinto di dover aggiornare il CUDA Toolkit e portarlo alla versione 13, perché PyTorch stava cercando librerie CUDA 13, indicate nei pacchetti con sigle come cu130. Poi, leggendo documentazione, forum e discussioni, e chiedendo aiuto anche a ChatGPT e a Diego, ho scoperto una cosa decisamente più interessante: il CUDA Toolkit installato nel sistema, nel mio caso, non mi serviva praticamente a nulla. Quello che mi serviva davvero era un driver NVIDIA sufficientemente recente da supportare il runtime CUDA richiesto dalle versioni moderne di PyTorch. I miei driver 550 arrivavano al supporto CUDA 12.4 e quindi, per utilizzare correttamente pacchetti costruiti per CUDA 13, avevo bisogno di un ramo driver più recente. Prima di toccare qualsiasi cosa, però, ho voluto capire meglio cosa stesse realmente usando il software che sul computer funzionava già.

ComfyUI: CUDA 12.4 senza dipendere dal Toolkit globale

Per attivare il venv di ComfyUI ho eseguito:

source ~/[cartella di comfyui]/bin/activate

e poi:

python -c "import torch; print('Torch:', torch.__version__); print('CUDA runtime:', torch.version.cuda); print('CUDA disponibile:', torch.cuda.is_available()); print('GPU:', torch.cuda.device_count())"

Il risultato era questo:

Torch: 2.6.0+cu124
CUDA runtime: 12.4
CUDA disponibile: True
GPU: 2

ComfyUI funzionava quindi con PyTorch cu124 e con il proprio runtime CUDA 12.4 all’interno dell’ambiente Python.

Le dipendenze presenti nel venv comprendevano infatti pacchetti come:

nvidia-cublas-cu12
nvidia-cuda-cupti-cu12
nvidia-cuda-nvrtc-cu12
nvidia-cuda-runtime-cu12
nvidia-cudnn-cu12
nvidia-cufft-cu12
nvidia-curand-cu12
nvidia-cusolver-cu12
nvidia-cusparse-cu12
nvidia-nccl-cu12
torch 2.6.0+cu124
torchvision 0.21.0+cu124

Il CUDA Toolkit globale non era quindi necessario per il normale utilizzo di ComfyUI.

Open WebUI ci dà un altro indizio

Nel venv di Open WebUI lo stesso controllo mostrava:

Torch: 2.12.0+cu130
CUDA runtime: 13.0
CUDA disponibile: False
GPU: 2

PyTorch rilevava le GPU, ma segnalava che il driver NVIDIA era troppo vecchio.

Questo era l’indizio decisivo: aggiornare il driver avrebbe sistemato non soltanto Unsloth, ma anche lo stack CUDA 13 già presente in Open WebUI.

Ed è qui che entrano davvero in scena i venv.

I venv: le piccole “scatole” che avevo sempre ignorato

Per semplificare a bestia cosa siano i virtual environment potrei paragonarli a delle piccole VM, ovvero ambienti separati tra loro. Però, prima che qualche sistemista mi lanci un forcone nella schiena, è meglio precisare subito che il paragone finisce praticamente qui: i venv non hanno un kernel, non virtualizzano hardware e non contengono un sistema operativo. Sono invece ambienti Python isolati, dentro i quali ogni applicazione può avere il proprio interprete, le proprie librerie e le proprie dipendenze senza andare a intaccare quelle utilizzate dalle altre applicazioni o dal Python installato nel sistema. Posso quindi avere, per esempio, un venv con una versione di PyTorch costruita per CUDA 12 e un altro con PyTorch e i relativi runtime CUDA 13. Non il CUDA Toolkit completo, sia chiaro, ma le librerie necessarie all’applicazione per utilizzare la GPU. Il driver NVIDIA, invece, rimane fuori da tutto questo ed è installato a livello di sistema. Deve semplicemente essere abbastanza recente da poter supportare le versioni CUDA richieste dalle applicazioni presenti nei vari venv. A quel punto la strada era chiara: il CUDA Toolkit 12.4 installato globalmente poteva tranquillamente uscire di scena, mentre il driver NVIDIA doveva essere aggiornato.

Rimozione del CUDA Toolkit globale

La prima cosa da fare era eliminare il CUDA Toolkit 12.4 che avevo installato mesi prima tramite il pacchetto `.run` di NVIDIA. Proprio perché l’installazione era stata fatta in quel modo, il Toolkit disponeva del proprio programma di disinstallazione:

sudo /usr/local/cuda-12.4/bin/cuda-uninstaller

Dopo la disinstallazione:

ls -ld /usr/local/cuda*

mostrava ancora:

/usr/local/cuda-12.4

ma:

ls -la /usr/local/cuda-12.4

rivelava che era rimasto praticamente soltanto:

nsight-systems-2023.4.4

Un residuo minuscolo.

ComfyUI continuava comunque a funzionare. Era la conferma pratica che il CUDA Toolkit globale, per quel tipo di utilizzo, non serviva.

Preparazione all’aggiornamento NVIDIA

Prima di modificare il driver ho controllato con precisione da dove stessi partendo.

cat /etc/os-release

riportava:

PRETTY_NAME="LMDE 7 (gigi)"
DEBIAN_CODENAME=trixie
DEBIAN_VERSION_FULL=13.0

Kernel:

uname -r
6.12.101+deb13-amd64

Architettura:

dpkg --print-architecture
amd64

Prima di toccare i driver ho verificato anche la presenza degli header del kernel:

sudo apt install linux-headers-$(uname -r)

che erano già installati.

Poi:

dkms status

per controllare che i moduli DKMS fossero correttamente presenti per i kernel installati.

Aggiunta del repository NVIDIA per Debian 13

Ho scaricato il keyring ufficiale:

wget https://developer.download.nvidia.com/compute/cuda/repos/debian13/x86_64/cuda-keyring_1.1-1_all.deb

e installato:

sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt update

Controllando:

apt-cache policy nvidia-driver

APT proponeva addirittura la serie 610.

Nel repository erano presenti le serie 590, 595 e 610. Ho scelto 590.48.01, evitando un salto ancora più aggressivo.

Pinning del driver 590.48.01

Provando a installare direttamente una versione specifica del driver, APT tentava di mischiare dipendenze appartenenti alle serie 550, 590 e 610.

Ho quindi cercato i pacchetti di pinning NVIDIA:

apt-cache search '^nvidia-driver-pinning'

Tra i risultati era presente:

nvidia-driver-pinning-590.48.01

Installazione:

sudo apt install nvidia-driver-pinning-590.48.01
sudo apt update

Dopo:

apt policy nvidia-driver

mostrava:

590.48.01-1 1000

La versione 590.48.01 aveva quindi priorità sulle versioni 595 e 610.

Questo permetteva ad APT di mantenere coerenti le dipendenze della stessa release NVIDIA.

DKMS e i vecchi kernel

Durante l’installazione del driver, DKMS ha compilato il modulo NVIDIA per tutti i kernel ancora presenti:

6.12.48
6.12.90
6.12.90+deb13.1
6.12.95
6.12.100
6.12.101

Verifica:

dkms status | grep nvidia

mostrava NVIDIA 590.48.01 installato sui vari kernel.

Per controllare il modulo del kernel corrente:

modinfo nvidia | grep -E '^(version|filename):'

Risultato:

filename: /lib/modules/6.12.101+deb13-amd64/updates/dkms/nvidia.ko.xz
version: 590.48.01

Primo reboot: conflitto con nouveau

Al primo riavvio, con kernel 6.12.101, compariva:

NVRM: GPU 0000:02:00.0 is already bound to nouveau

e il sistema non rispondeva più.

Con il kernel 6.12.100 riuscivo invece ad arrivare in TTY. Digitando:

startx

Cinnamon partiva.

Questo indicava che kernel, Xorg e desktop non erano completamente compromessi. Il problema riguardava soprattutto l’inizializzazione automatica tramite LightDM e lo stack NVIDIA durante il boot.

Configurazione della GPU primaria

La workstation dual-GPU aveva già una configurazione Xorg specifica.

Controllo:

grep -RniE 'BusID|PCI:1|nvidia' /etc/X11 /etc/lightdm 2>/dev/null

Risultato:

/etc/X11/xorg.conf.d/10-primary-gpu.conf:3: Driver "nvidia"
/etc/X11/xorg.conf.d/10-primary-gpu.conf:4: BusID "PCI:1:0:0"

La RTX 3060 sul bus 01:00.0 rimaneva quindi la GPU primaria per il display.

nvidia-smi era sparito

Dopo il cambio di packaging:

ls -l /usr/bin/nvidia-smi

restituiva file inesistente.

Controllando:

dpkg -l | grep -E 'nvidia-smi|nvidia-driver|nvidia-kernel'

risultava:

nvidia-smi 590.48.01-1 Transitional dummy package

E:

dpkg -L nvidia-smi

mostrava praticamente soltanto documentazione.

Il pacchetto nvidia-smi era quindi diventato un pacchetto di transizione nel nuovo repository.

Installazione dei componenti compute NVIDIA

Ho verificato:

apt policy nvidia-driver-cuda

ottenendo:

Candidato: 590.48.01-1

nvidia-driver-cuda non è il CUDA Toolkit completo: installa componenti compute associati al driver NVIDIA.

Prima di procedere ho simulato:

sudo apt install --simulate nvidia-driver-cuda

APT proponeva di rimuovere il vecchio pacchetto dummy nvidia-smi e installare componenti come:

libcudadebugger1
libnvidia-fbc1
libnvidia-nvvm4
libnvidia-opticalflow1
libnvidia-present
libnvidia-sandboxutils
libnvoptix1
nvidia-opencl-icd
nvidia-driver-cuda

Dopo l’installazione:

nvidia-smi

funzionava nuovamente:

NVIDIA-SMI 590.48.01
Driver Version: 590.48.01
CUDA Version: 13.1

ed entrambe le RTX 3060 venivano rilevate.

LightDM e il problema GLX

Ma tornando al mancato avvio, da TTY LightDM risultava attivo:

systemctl status lightdm --no-pager -l

e la configurazione conteneva già un ritardo:

systemctl cat lightdm
[Service]
ExecStartPre=/bin/sleep 3

Analizzando Xorg è emerso un problema con il modulo GLX NVIDIA.

Ho cercato:

sudo find /usr -name 'libglxserver_nvidia.so*' -o -name 'libglxserver_nvidia.so' 2>/dev/null

Risultato:

/usr/lib/xorg/modules/extensions/libglxserver_nvidia.so.590.48.01

Il file esisteva, ma mancava il collegamento generico libglxserver_nvidia.so.

Verifica del pacchetto proprietario:

dpkg -S /usr/lib/xorg/modules/extensions/libglxserver_nvidia.so.590.48.01

Risultato:

xserver-xorg-video-nvidia

Ho quindi creato il symlink:

sudo ln -s /usr/lib/xorg/modules/extensions/libglxserver_nvidia.so.590.48.01 
/usr/lib/xorg/modules/extensions/libglxserver_nvidia.so

Controllo:

ls -l /usr/lib/xorg/modules/extensions/libglxserver_nvidia.so*

Il link risultava correttamente creato.

Tornando in TTY e riavviando LightDM:

sudo systemctl restart lightdm

la schermata di login è apparsa.

Situazione NVIDIA finale

Dopo il reboot:

nvidia-smi

mostrava:

NVIDIA-SMI 590.48.01
Driver Version: 590.48.01
CUDA Version: 13.1

Le due schede:

GPU 0: NVIDIA GeForce RTX 3060 - PCI 01:00.0 - Display On
GPU 1: NVIDIA GeForce RTX 3060 - PCI 02:00.0 - Display Off

Xorg e Cinnamon utilizzavano principalmente la prima GPU, come previsto dalla configurazione BusID "PCI:1:0:0".

Pulizia dei vecchi kernel

Controllo dei kernel e degli header:

dpkg -l | grep -E 'linux-image|linux-headers' | grep '6.12'

Ho mantenuto soltanto:

6.12.101  - kernel principale
6.12.100  - kernel di backup

e rimosso i kernel più vecchi:

6.12.95
6.12.90
6.12.90+deb13.1
6.12.48

insieme ai relativi header.

Dopo la pulizia:

dkms status

mostrava soltanto i moduli relativi ai kernel 100 e 101:

broadcom-sta
nvidia/590.48.01
v4l2loopback

Anche /boot era finalmente ridotto ai due kernel necessari:

ls -lh /boot

Attenzione ad apt autoremove

Prima di eseguire una pulizia automatica ho lanciato:

apt autoremove --dry-run

APT proponeva di eliminare anche:

glx-alternative-mesa
glx-alternative-nvidia
glx-diversions
update-glx

oltre ad alcune librerie i386 NVIDIA/Mesa.

Dopo i problemi appena risolti con GLX, la scelta prudente è stata non eseguire quell’autoremove alla cieca.

La simulazione --dry-run è utile proprio per questo: permette di vedere cosa verrebbe eliminato senza modificare il sistema.

Open WebUI dopo il driver 590

Prima dell’upgrade:

Torch: 2.12.0+cu130
CUDA runtime: 13.0
CUDA disponibile: False

Dopo il driver 590, nel relativo venv:

python -c "import torch; print('Torch:', torch.__version__); print('CUDA runtime:', torch.version.cuda); print('CUDA disponibile:', torch.cuda.is_available()); print('GPU:', torch.cuda.device_count())"

Risultato:

Torch: 2.12.0+cu130
CUDA runtime: 13.0
CUDA disponibile: True
GPU: 2

Il problema era quindi realmente il vecchio driver 550.

Test CUDA reale sulle due RTX 3060

Non mi sono limitato a verificare torch.cuda.is_available().

Ho eseguito un vero calcolo CUDA su entrambe le schede:

python - <<'PY'
import torch

print("Torch:", torch.__version__)
print("CUDA:", torch.version.cuda)
print("GPU rilevate:", torch.cuda.device_count())

for i in range(torch.cuda.device_count()):
    print(f"nGPU {i}: {torch.cuda.get_device_name(i)}")
    x = torch.randn((4096, 4096), device=f"cuda:{i}")
    y = x @ x
    torch.cuda.synchronize(i)
    print("Calcolo CUDA: OK")
    print(f"VRAM allocata: {torch.cuda.memory_allocated(i)/1024**2:.1f} MiB")

print("nEntrambe le GPU funzionano correttamente.")
PY

Risultato:

Torch: 2.12.0+cu130
CUDA: 13.0
GPU rilevate: 2

GPU 0: NVIDIA GeForce RTX 3060
Calcolo CUDA: OK
VRAM allocata: 136.1 MiB

GPU 1: NVIDIA GeForce RTX 3060
Calcolo CUDA: OK
VRAM allocata: 136.1 MiB

Entrambe le GPU funzionano correttamente.

Questa è una verifica molto più significativa del semplice rilevamento delle schede: PyTorch ha realmente eseguito codice CUDA su entrambe le GPU.

A quel punto potevo finalmente tornare al motivo per cui era iniziato tutto questo casino.

Unsloth.

Installazione pulita di Unsloth Studio

Con il sistema finalmente sistemato ho rilanciato l’installer di Unsloth.

L’installer ha rilevato:

torch 2.11.0+cu130

e ha installato automaticamente componenti compatibili, tra cui:

torchao==0.17.0

La versione installata di Unsloth:

unsloth 2026.8.16

All’avvio Studio ha finalmente mostrato:

Hardware detected: CUDA -- NVIDIA GeForce RTX 3060
CUDA devices (2, CUDA_DEVICE_ORDER=PCI_BUS_ID):
  [0] NVIDIA GeForce RTX 3060
  [1] NVIDIA GeForce RTX 3060

Entrambe le GPU venivano quindi rilevate correttamente.

Primo modello di prova

Come primo test ho scelto:

Qwen3.6-27B-MTP-GGUF · UD-Q4_K_XL

Un modello abbastanza grande da rendere interessante la verifica della distribuzione sulle due RTX 3060.

Per monitorare le GPU è particolarmente comodo:

nvtop

Rispetto a:

watch -n 1 nvidia-smi

nvtop permette di osservare più comodamente utilizzo di GPU 0 e GPU 1, VRAM occupata, processi e andamento del carico in tempo reale.

Il test importante è distinguere tra Unsloth rileva due GPU e Unsloth utilizza realmente entrambe per il modello.

Sono due cose diverse.

Unsloth Studio e la generazione immagini

Un’altra sorpresa è stata la sezione immagini integrata direttamente in Unsloth Studio.

L’interfaccia mette a disposizione funzioni come:

Create
Transform
Inpaint
Extend
Upscale
Reference
Edit

oltre a prompt, negative prompt, aspect ratio, risoluzione e numero di step.

Questo significa che Studio non è soltanto una GUI per LLM o un’alternativa a Ollama.

Si presenta come un ambiente locale più ampio per LLM, modelli Hugging Face, GGUF, training e fine-tuning, generazione e modifica di immagini e gestione di altri modelli AI.

ComfyUI rimane naturalmente molto più adatto ai workflow grafici complessi, ma Unsloth Studio dispone di una propria interfaccia per le immagini e non deve necessariamente appoggiarsi a ComfyUI come frontend.

Ed è quasi comico pensare che tutto questo viaggio sia iniziato perché volevo semplicemente generare un’immagine “spiccia”.

Configurazione finale

LMDE 7 / Debian 13
│
├── Kernel
│   ├── 6.12.101  <- principale
│   └── 6.12.100  <- backup
│
├── NVIDIA
│   ├── Driver 590.48.01
│   ├── supporto CUDA driver: 13.1
│   ├── RTX 3060 12 GB #0
│   └── RTX 3060 12 GB #1
│
├── CUDA Toolkit globale
│   └── NON NECESSARIO per questi workload
│
├── ComfyUI
│   └── Torch 2.6.0 + cu124
│
├── Open WebUI
│   └── Torch 2.12.0 + cu130
│
├── Unsloth Studio
│   ├── Unsloth 2026.8.16
│   ├── Torch 2.11.0 + cu130
│   └── 2 × RTX 3060 rilevate
│
└── LightDM
    ├── GPU primaria PCI:1:0:0
    └── ExecStartPre=/bin/sleep 5

La configurazione concettuale, invece, è ancora più semplice:

                    DRIVER NVIDIA 590
                          │
                  supporto CUDA 13.1
                          │
          ┌───────────────┼───────────────┐
          │               │               │
       ComfyUI        Open WebUI       Unsloth
          │               │               │
      Torch cu124     Torch cu130     Torch cu130
          │               │               │
      runtime suo     runtime suo     runtime suo

Ogni ambiente Python può portarsi dietro le librerie CUDA richieste dalla propria build di PyTorch.

Il sistema operativo deve invece fornire un driver NVIDIA sufficientemente recente da supportare quei runtime.

Il risultato pratico è che PyTorch cu124 e cu130 possono convivere sulla stessa macchina, anche senza installare globalmente CUDA Toolkit 12.4 o CUDA Toolkit 13.

Conclusione

Quando ho assemblato questa workstation pensavo soprattutto all’hardware: due RTX 3060, tanta VRAM complessiva, una vecchia piattaforma X99 ancora perfettamente sfruttabile e abbastanza PCI Express da poter giocare con due schede senza segarle brutalmente. Alla fine, invece, la parte più interessante è stata quella software. Ho capito meglio la differenza tra driver NVIDIA, CUDA Toolkit e runtime CUDA. Ho scoperto che per i programmi che utilizzo ogni giorno il Toolkit globale non era necessario, che ogni venv può vivere tranquillamente con il proprio stack PyTorch/CUDA e che il vero requisito comune a tutti è un driver sufficientemente recente. Nel frattempo ho anche convinto LightDM ad aspettare cinque secondi, sistemato Xorg, combattuto con GLX, aggiornato mezzo stack NVIDIA, ripulito kernel e verificato con un calcolo reale che entrambe le RTX 3060 funzionassero correttamente.

… e son solo partito da “provo Unsloth”.

La normale esperienza Linux di un pomeriggio qualsiasi.

Ma il viaggio non è ancora finito.

Adesso che il sistema è finalmente stabile e Unsloth vede entrambe le schede, resta la domanda più interessante: quanto riesco davvero a sfruttare due RTX 3060 da 12 GB rispetto a una singola GPU con 24 GB di VRAM contigua?

Ed è da lì che continuerò.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *