CUDA/cuDNN/TF2.x on Ubuntu

Questa guida ha l’obbiettivo di aiutare nell’installazione di una nuova versione dei CUDA/cuDNN sul proprio sistema, volto fondamentalmente all’utilizzo con TensorFlow.

L’obiettivo principale è quello di essere più generale possibile, per permettere di installare qualsiasi versione CUDA/cuDNN/TensorFlow che si voglia su qualunque versione di Ubuntu.

NOTA: Al momento della scrittura di questa guida non esistono versioni di TensorFlow ufficialmente supportate per Ubuntu 20.04 e successivi.

ubuntu_cuda

Perché questa guida?

Una domanda assolutamente lecita, dal momento che esistono diverse guide di questo genere sul web, ufficiali e non. Peccato che nessuna di queste sia venuta veramente in aiuto quando ho dovuto sostituire la versione di TensorFlow sul mio pc con una meno recente. Questa guida nasce nella speranza di evitare ad altri la mia esperienza, costituita da ore e ore spese a disinstallare e reinstallare software, drivers e interi sistemi operativi.

Come sappiamo, affinché TensorFlow possa funzionare correttamente su una macchina dotata di GPU dedicata, sono necessari entrambi i software, CUDA e cuDNN. Di entrambi esistono diverse versioni, e ne vengono rilasciate continuamente di nuove.

Questa guida vuole essere il più generale possibile, per permettere di installare la versione più aggiornata del software così come la più datata presente sul web, su qualunque versione di Ubuntu si voglia, per venire incontro ad ogni esigenza.

La guida presente sul sito di TensorFlow fallisce in questo, in quanto permette solamente di installare le versioni più aggiornate. Allo stesso modo, la maggior parte delle guide non ufficiali che si trovano sul web, mirano all’installazione di una precisa versione del software, di conseguenza risultano obsolete spesso a distanza anche solo di pochi mesi.

Come decidere quale versione utilizzare

Se il vostro obiettivo è solo quello di eliminare completamente CUDA e cuDNN dal vostro sistema operativo, allora è possibile saltare tranquillamente questa sezione, e seguire direttamente la sezione “Come rimuovere completamente CUDA e cuDNN” (e probabilmente anche “Come reinstallare i driver grafici Nvidia”).

Se invece si vuole un’installazione pulita che permetta di utilizzare TensorFlow, innanzitutto è necessario capire che versione utilizzerete.

https://www.tensorflow.org/install/source#linux

Questa tabella, sotto la voce GPU, elenca le versioni CUDA/cuDNN compatibili con ogni versione di TensorFlow. Per esperienza personale, posso dirvi che è assolutamente necessario seguire queste indicazioni, a meno che non vogliate creare delle chimere di versioni che non porteranno a nulla se non a valanghe di errori alla prima istanza che proverete a lanciare con TensorFlow.

Quindi, prima di procedere, segnatevi bene che versione di TensorFlow avete intenzione di installare, e di conseguenza tutte le versioni annesse di CUDA e cuDNN.

Se per esempio volessimo installare TensorFlow 2.3, avremo bisogno di CUDA 10.1 e cuDNN 7.6.

Come rimuovere completamente CUDA e cuDNN

Prima di imparare l’utilizzo di questo metodo, messo a punto empiricamente con una serie di trial-and-error, l’unico modo che possedevo per avere la CERTEZZA di lavorare in un ambiente privo di ogni installazione Nvidia pregressa era la reinstallazione completa del sistema operativo. “Un po’ estremo”, penserete, ma quando si tratta di Ubuntu, esistono software particolarmente avvezzi a lasciare tracce di sé in ogni singola directory presente sul sistema.

Con mia grande sorpresa, ho scoperto che non è il caso dei software Nvidia, MA devo mettervi subito in guardia: seguendo i passi che verranno mostrati a breve, andremo a cancellare qualunque traccia di driver Nvidia da Ubuntu. Se questo è necessario per riuscire a rimuovere completamente CUDA e cuDNN, su alcuni sistemi potrebbero causare dei problemi al riavvio del sistema. Se dovesse capitarvi, vi rimando all’ultima sezione della guida.

Partiamo subito con:

				
					sudo apt update
				
			

A questo punto iniziamo togliendo dal computer qualsiasi traccia di driver CUDA

				
					 sudo apt purge cuda*
				
			

seguito da

				
					sudo rm -rf /usr/local/cuda*
				
			

e infine

				
					sudo apt update
sudo apt autoremove

				
			

Facciamo la stessa cosa con i driver cuDNN:

				
					sudo apt purge libcudnn*
sudo apt update
sudo apt autoremove


				
			

A questo punto, per essere certi di aver rimosso CUDA/cuDNN, e per ottenere una reainstallazione pulita, rimuoviamo ogni traccia di Nvidia dal nostro sistema:

				
					sudo apt remove --purge '^nvidia-.*'
sudo apt update
sudo apt autoremove

				
			

A questo punto riavviamo il sistema. Al riavvio, avrete perso qualunque driver grafico, di conseguenza la risoluzione dello schermo sarà quella minima supportata dal sistema. Non preoccupatevi, è assolutamente normale. Se invece, come premettevo prima, dovreste avere problemi ancor prima della riaccensione, come bug e glitch grafici che non vi permettono nemmeno di accedere a Ubuntu, vi rimando nuovamente all’ultima sezione della guida.

Complimenti, avete rimosso completamente ogni traccia di CUDA e cuDNN presente sul vostro sistema!

Come reinstallare i driver grafici Nvidia

Premetto innanzitutto che la versione dei driver grafici Nvidia è completamente indipendente dalla versione CUDA/cuDNN/TensorFlow. Dato che il sistema tenterà, ogni volta che ne ha possibilità, di aggiornare i driver grafici, in questa fase io consiglio di installare sempre i driver più aggiornati tra quelli compatibili con la propria scheda grafica.

Procediamo quindi con l’installazione: solitamente su Ubuntu è sufficiente aprire il “Software Updater” e cliccare su “Settings…”.

Nella nuova finestra che si aprirà andate nella scheda “Additional Drivers”, dopodichè selezionate la versione dei driver Nvidia che preferite. Cliccate su “Apply Changes” e chiudete le finestre. Al riavvio del pc i driver saranno correttamente installati, dovreste accorgervene subito dalla risoluzione dello schermo, che a questo punto dovrebbe essere quella nativa.

Per essere certi che i driver siano stati installati correttamente, aprite un terminale e digitate:

				
					nvidia-smi
				
			

dovrebbero apparirvi varie informazioni riguardo la vostra scheda Nvidia, tra cui anche la versione dei drivers.

NOTA: in nvidia-smi, in alto a destra, comparirà anche una voce riferita ai driver CUDA. Questa voce in realtà non si riferisce alla versione installata sul sistema, ma quella compatibile più recente per la vostra scheda grafica. Di conseguenza ignoratela completamente e soprattutto non usatela come riferimento per controllare che versione CUDA è attualmente installata (vedremo in seguito come eseguire correttamente questo check), dal momento che tale voce appare anche se i driver CUDA non sono affatto installati sul sistema!

NOTA: Se dal Software Updater avete selezionato un driver proprietario Nvidia (al fondo è presente la dicitura “(proprietary)” o “(proprietary, tested)”), durante l’installazione di CUDA e cuDNN è molto probabile che questo verrà sostituito con un driver open source (nuovamente, riconoscibile per la dicitura “(open source)” al fondo) di pari versione. Se per esempio avete installato la versione “…nvidia-driver-450 (proprietary)”, è molto probabile che questa venga sostituita con “…nvidia-driver-450 (open source)”. Questo è perfettamente normale e voluto, quella versione open source sarà la versione che terrete e userete da qui in avanti quindi, mi raccomando, non cercate di cambiare questa versione durante o dopo l’installazione se non volete buttare nel cestino l’intera installazione dei driver CUDA.

Se vi è stato impossibile seguire la procedura perché sul Software Updater trovate le versioni driver Nvidia oscurate e non potete cliccarci sopra, vi rimando all’ultima sezione della guida.

Come installare CUDA e cuDNN

Eccoci, siamo finalmente arrivati alla parte più attesa dell’intera guida. Prima di procedere voglio rispondere ad un paio di domande che potrebbero esservi sorte:

  1. Perché non posso installare i driver direttamente con “apt install”? Se ci aveste già provato saprete la risposta: semplicemente mancano le key per farlo, e in mancanza di esse il sistema non possiede una repository autorizzata a scaricare i nostri driver
  2. Perché non seguire la guida sul sito ufficiale di TensorFlow? Come detto in precedenza, quella guida permette di installare solamente la versione più aggiornata
  3. Perché non posso installare i driver CUDA e cuDNN seguendo la guida sul sito ufficiale Nvidia? Quella guida non fornisce la key per scaricare i driver attraverso “apt install”, ma solamente per scaricare il file debian di una (e una sola) versione del driver, che viene poi estratta e installata. Se questa procedura funziona con i driver più recenti, alcuni di questi file debian più datati non sono più disponibili al download attraverso quella procedura.

Dato risposta a queste domande, incominciamo. Da terminale, eseguite (NOTA: queste linee sono utilizzate per il sistema Ubuntu 18.04 Bionic Beaver. Per installare su altra versione, sostituite ogni “1804” con la vostra versione di Ubuntu)

				
					wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt update
wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt install ./nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt update

				
			

In questo modo abbiamo aggiunto al sistema le chiavi per la repository Nvidia developer.

A questo punto installiamo la versione CUDA che abbiamo scelto in precedenza con:

				
					sudo apt install <versione_cuda>
				
			

Dove al posto di <versione_cuda> dovete inserire la versione scelta nel formato

				
					cuda-**-*
				
			

Che nel nostro esempio sarà

				
					sudo apt install cuda-10-1
				
			

Ora, l’installazione dei cuDNN è un po’ più complicata: per ogni versione CUDA esistono diverse versioni cuDNN, ma a noi interessano solo alcune di queste.

Andate quindi alla pagina web con l’archivio di tutte le versioni cuDNN

https://developer.nvidia.com/rdp/cudnn-archive

E cercate la versione che vi interessa. Rimanendo in esempio, TensorFlow 2.3 necessita di cuDNN 7.6 per CUDA 10.1. Al momento della scrittura di questa guida, esistono versioni cuDNN 8.* per CUDA 10.1, ma a noi serve necessariamente la versione 7.6. Tra le varie versioni “cuDNN 7.6.* for CUDA 10.1”, consiglio di scaricare sempre la più recente.

Una volta che avrete capito quale versione installare, cliccateci sopra e vi si aprirà una tendina.

Cercate “cuDNN Runtime Library for Ubuntu**.** (Deb)” con la vostra versione Ubuntu al posto degli asterischi ma non cliccateci sopra, altrimenti avrete bisogno di un account developer per scaricare il file debian. Invece, andateci sopra con il puntatore e leggete il percorso del link a cui conduce, in basso a sinistra del vostro browser. Prendete solamente l’ultima voce del percorso, che è il nome del file debian.

Per esempio, per la versione cuDNN 7.6.5 for CUDA 10.1, questo nome è “libcudnn7_7.6.5.32-1+cuda10.1_amd64.deb”

A questo punto possiamo finalmente scaricare i nostri driver cuDNN. Nel terminale

				
					sudo apt install libcudnn*=<versione_cudnn>
sudo apt install libcudnn*-dev=<versione_cudnn>

				
			

dove, al posto dell’asterisco dovrete mettere la versione del driver scelto, e al posto di <versione_cudnn>, dovrete inserire il nome del file debian recuperato prima, togliendo la parte iniziale “libcudnn*_” e togliendo la parte finale “_amd64.deb”.

Nel nostro esempio, questo comando sarà

				
					sudo apt install libcudnn7=7.6.5.32-1+cuda10.1
sudo apt install libcudnn7-dev=7.6.5.32-1+cuda10.1

				
			

Verificare l’installazione di CUDA e cuDNN

A questo punto CUDA e cuDNN dovrebbero essere installati, ma affinché il sistema possa vederli dobbiamo aggiungere al nostro .bashrc

				
					# NVIDIA CUDA Toolkit
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64

				
			

NOTA: durante l’installazione dei cuda, nel percorso “/usr/local/” vengono generate automaticamente due directory:

  1. cuda-**.*, con al posto degli asterischi la versione installata
  2. cuda, un soft-link a cuda-**.*

Se in “/usr/local” trovate un’altra directory cuda-**-*, riportante una versione che voi NON avete installato, molto probabilmente quella è la versione a cui fare riferimento per le librerie.

Quindi dobbiamo modificare queste linee nel .bashrc:

				
					# NVIDIA CUDA Toolkit
export PATH=/usr/local/cuda-**.*/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-**.*/lib64

				
			

Dove il “PATH”, al posto degli asterischi, deve riportare la versione CUDA che voi avete installato, mentre “LD_LIBRARY_PATH” deve riportare la versione che NON avete installato, ma di cui vi siete trovati la cartella in “/usr/local/”.

Per accertarci che sia andato tutto per il verso giusto, apriamo un nuovo terminale (è importante a meno che non facciate un source al .bashrc) e scriviamo

				
					nvcc --version
				
			

Effettuiamo lo stesso controllo anche per i cuDNN. Provate con

				
					cat /usr/include/cudnn.h | grep CUDNN_MAJOR -A 2
				
			

se non dovesse funzionare

				
					cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
				
			

Anche in questo caso dovreste leggere dei messaggi riguardanti la versione dei driver. In particolare dovreste vedere i dati relativi a major, minor e patch level version, indicati con “CUDNN_MAJOR”, “CUDNN_MINOR” e “CUDNN_PATCHLEVEL”.

Nel nostro esempio, per la versione cuDNN 7.6.5, questi tre valori valgono rispettivamente 7, 6 e 5.

Se entrambi i check sono andati a buon fine, complimenti, avete installato con successo i driver CUDA e cuDNN!

Come accertarsi che CUDA e cuDNN funzionino con TensorFlow

Una volta installata la versione TensorFlow che desideravate (molto consigliato usare un virtual environment. Maggiori informazioni QUI), con 

				
					pip3 install tensorflow-gpu==<versione_TF>
				
			

dove al posto di <versione_TF> dovete inserire la versione desiderata, nel fomato

major_version.minor_version.patch_version

Per esempio, nel nostro caso

				
					pip3 install tensorflow-gpu==2.3.1
				
			

Per testare che l’installazione sia andata a buon fine, lanciate questo python di controllo

				
					python3 -c "import tensorflow as tf; print(tf.__version__); print("The following GPU devices are available: %s" % tf.test.gpu_device_name())"

				
			

Se tutto va per il verso giusto, la prima riga di codice dovrebbe stampare a schermo la versione di TensorFlow installata, mentre la seconda serve per controllare che TensorFlow riesca a ‘vedere’ le GPU disponibili, e in caso positivo stampa l’ID del dispositivo.

Se ciò non dovesse accadere e restituisse invece degli errori, vi invito a controllare attentamente l’ultima sezione della guida, dove cerchiamo di risolvere alcuni di questi errori che possono nascere durante e dopo l’installazione dei driver CUDA e cuDNN.

Problemi conosciuti e soluzioni più comuni

  •  Dopo la disinstallazione dei driver nvidia il mio pc non si riavvia correttamente/escono numerosi glitch grafici che non mi permettono di accedere a Ubuntu

E’ un problema ben conosciuto e per cui esistono diverse guide online che spiegano per filo e per segno da cosa è causato l’errore. Di seguito mi limiterò a elencare i passaggi da seguire per risolverlo e riottenere l’accesso a Ubuntu.

  • Avviate il pc;
  • Su GRUB, andate sulla voce “UBUNTU XX.XX” corrispondente alla vostra versione ma NON selezionatela;
  • Premete invece il tasto “e”;
  • Verso il fondo del file che vi si aprirà troverete la voce “linux /boot/vmlinuz***” (cambia a seconda della versione software), scrivete “nomodeset” prima di “quiet splash”;
  • Premete la combinazione di tasti “ctrl+x”

A questo punto dovrete avere accesso a Ubuntu. Questa procedura si rende necessaria ogni volta che proviate ad accedere a Ubuntu senza driver grafici installati.

Per evitare di doverla eseguire ad ogni accensione avete dunque due alternative:

    1. Installate i driver grafici (come indicato alla sezione “Come reinstallare i driver grafici Nvidia”);

Oppure

  1. Cambiate il file di lancio di grub, in modo da avere “nomodeset” sempre inserito:
    1. Su terminale, digitate “sudo gedit /etc/default/grub”
    2. Alla voce “GRUB_CMDLINE_LINUX_DEFAULT” scrivete “nomodeset” prima di “quiet splash”, quindi salvate il documento;
    3. Sempre su terminale, digitate “sudo update-grub”
  • Mi è impossibile installare i driver Nvidia dal Software Updater. Le versioni dei driver sono oscurate (in grigetto) e non posso cliccarci sopra

Altro problema ben conosciuto, ma per il quale ho faticato un po’ di più per ottenere una risposta risolutiva.

Aprite un terminale

				
					sudo apt update
sudo ubuntu-drivers autoinstall

				
			

Se questo comando risolve il problema buon per voi, ma di solito non è così semplice, e potreste ottenere un errore al fondo del quale si può leggere

E: Unmet dependencies. Try ‘apt –fix-broken install’ with no packages (or specify a solution).

In questo caso lanciate, come consigliato

				
					sudo apt --fix-broken install
				
			

Nuovamente, se questo risolve i vostri problemi, bene per voi, se invece ricevete un altro errore, andate in fondo dove troverete

Errors were encountered while processing:

 /var/********.deb

E: Sub-process /usr/bin/dpkg returned an error code (1)

In questo caso lanciate da terminale il comando

				
					sudo dpkg -i --force-overwrite <path-to-the-deb-file>
				
			

dove al posto di <path-to-the-deb-file> dovete copia e incollare tutta la linea con nome e percorso del file che vi restituisce l’errore (nel mio esempio è “ /var/********.deb”).

Dopodichè lanciate nuovamente

				
					sudo apt update
sudo ubuntu-drivers autoinstall

				
			

A questo punto se tornate al Software Updater vi sarà possibile selezionare i driver Nvidia da installare.

  • Quando lancio il file python di controllo ottengo l’errore:

    “kernel version ****** does not match DSO version ****** — cannot find working devices in this configuration”

Un altro problema noto, meno nota la causa scatenante. Non azzardatevi a cambiare versione dei driver Nvidia installati sul vostro pc, questo porterà semplicemente alla rimozione di qualunque driver CUDA e cuDNN dal vostro vostro pc al prossimo comando “apt autoremove” che lancerete.

In tutti i casi che ho visto questo errore (e anche dalle risposte trovate online), il metodo corretto è semplicemente quello di riavviare il sistema.

Se questa soluzione non dovesse funzionare al primo avvio, lanciate un “sudo apt update” da terminale e riprovate col riavvio. Se nemmeno così il problema viene risolto, è probabile che abbiate cambiato i driver grafici Nvidia durante o dopo l’installazione dei CUDA.

In questo caso la soluzione migliore è quella di riseguire l’intera guida, rimuovere completamente ogni traccia Nvidia dal pc e reinstallare CUDA e cuDNN, questa volta senza toccare i driver grafici Nvidia a meno che non venga esplicitamente richiesto dalla guida (e seguendo bene anche tutte le NOTE presenti all’interno della guida, compresa quella in cui dicevo di non cambiare i driver grafici durante e dopo l’installazione dei CUDA).

  • Quando lancio il file python di controllo o quando lavoro con TensorFlow ottengo l’errore “Could not load dynamic library ‘libcu**********’”

Se la libreria dinamica che il programma non riesce ad aprire inizia con “libcu…” state pur certi che è una libreria CUDA/cuDNN. Capire questo è già un buon punto di partenza.

Che sia una libreria CUDA o cuDNN poco importa, esistono numerosi motivi scatenanti per questo errore tra cui fare distinzione:

  1. Il programma vuole aprire una libreria che fa riferimento ad una versione diversa da quella installata:

    Per esempio, l’errore richiede la libreria ‘libcudart.so.10.1’ ma noi abbiamo installato CUDA 10.2. La maggior parte dei casi, un errore di questo tipo indica che abbiamo installato una versione CUDA (o cuDNN) errata, per esempio se abbiamo installato CUDA 10.2 per TensorFlow 2.3.0 (che richiede invece CUDA 10.1).

    Un’altra possibilità è che abbiate sbagliato a scaricare la versione di TensorFlow.

    Se invece sei sicuro di aver installato la versione corretta di tutti i software, vedi la risposta al punto tre.

  2. Il programma vuole aprire una libreria che fa riferimento ad una versione uguale a quella installata:

    Quasi sicuramente qualcosa è andato storto durante l’installazione. Consiglio di seguire la guida per rimuovere e reinstallare tutto, oppure prova con la risposta al punto tre.

  3. Il programma vuole aprire una libreria che non fa riferimento a nessuna versione in particolare:

    Per esempio, l’errore richiede la libreria ‘libcublas.so.10”, non sappiamo quindi se si riferisce alla versione 10.0, 10.1 o 10.2.

    La regola di base è: se dopo aver installato i driver CUDA, lanciando

    “sudo apt update” and “sudo apt upgrade”

    al percorso /usr/local/ trovate una directory cuda-**.* con versione diversa da quella da voi installata, è molto probabile che quella sia la directory a cui fare riferimento per le librerie da utilizzare.

    Per esempio, andando a installare la versione CUDA 10.1, verrà creata anche una directory /usr/local/cuda-10.2 all’interno della quale sono presenti solo tre cartelle: “include”, “lib64” e “targets”.

    Questo nasce dal fatto che i file di libreria associati ad una major version (CUDA 10, CUDA 11) vengono installati solamente con la minor version più recente (in questo caso CUDA 10.2 è una minor version più recente di CUDA 10.1). “E’ necessario?!” vi chiederete. Certo che no, ma evidentemente agli sviluppatori Nvidia piace fare del male a noi poveri utenti. Al momento di scrittura di questa guida la versione più recente è CUDA 11.2: non è verificato  ma, analogamente, è probabile che per far funzionare correttamente CUDA 11.0 e 11.1 siano necessarie le librerie di CUDA 11.2.

    Se ciò vi capita dovete quindi aprire il vostro .bashrc, dove avevamo scritto

    # NVIDIA CUDA Toolkit

    export PATH=/usr/local/cuda-**.*/bin:$PATH

    export LD_LIBRARY_PATH=/usr/local/cuda-**.*/lib64

    PATH non va toccato, lasciate ciò che avevate scritto, in quanto dovrà fare riferimento alla versione CUDA da voi installata, mentre LD_LIBRARY_PATH dovrà far riferimento all’altra versione installata automaticamente.

    Per esempio, quando installiamo CUDA 10.1, avremo bisogno delle librerie nella cartella cuda-10.2 affinché tutto funzioni correttamente, quindi nel .bashrc scriveremo

    # NVIDIA CUDA Toolkit

    export PATH=/usr/local/cuda-10.1/bin:$PATH

    export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64