NVIDIA GPU & CUDA
Tags: gpu, cuda, nvidia, linux
Published: 2024-01-18 17:56:28

Tengo instalada la distro https://neon.kde.org/ (iso: neon-user-20231221-0716.iso), y una tarea pendiente por falta de tiempo siempre ha sido instalar *CUDA* en mi Linux.

---

# Documentación

Para instalar los drivers nativos de *Nvidia* hemos seguido los pasos indicados en su web: [NVIDIA](https://www.nvidia.com/es-es/geforce/drivers/). Una vez selecciones el driver, podrás descargarlo y también leer la documentación.

Para instalar los drivers nativos de *Cuda* también hemos seguido los pasos de Nvidia: [CUDA-DOC](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#), [CUDA-DRIVERS](https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=22.04&target_type=runfile_local)

Aunque *Cuda* también instala los drivers, yo prefiero realizar esta acción con anterioridad; evitando así que algún error proveniente de la instalación de los drivers me confunda con errores de la instalación de *Cuda*.
 
---

# Índice<a name="index"></a>

- [Instalación](#chapter-1)
  - [Preparación](#chapter-1a)
  - [Método 1: Instalar desde los repositorios de *Neon*](#chapter-1b)
  - [Método 2: Utilizar los instaladores de *Nvidia*](#chapter-1c)
- [Configuración](#chapter-2)
  - [Configurar CUDA](#chapter-2a)
  - [Configurar NVIDIA](#chapter-2b)
- [Terminar la instalación](#chapter-3)

---

[-^-](#index)
# Instalación<a name="chapter-1"></a>

Hemos hecho una incursión en tres formas diferentes de realizar la instalación, así podemos ver cuál es la mejor opción para nuestra distro.

La primera opción que tomamos fue instalarlo directamente de los repositorios de la distro, la segunda fue descargando los instaladores de *Nvidia*.

Pero, vayamos por partes.

[-^-](#index)
## Preparación (apto para ambos métodos de instalación)<a name="chapter-1a"></a>

Lo primero que hice fue instalarme la utilidad *nvtop* para poder ver gráficamente la información en tiempo real del funcionamiento de la GPU. Mi equipo tiene como gráfica principal una gráfica Intel de 300Mhz y con N/A (vamos, ná de ná) de memoria dedicada; además, posee una segunda gráfica NVIDIA GeForce 940MX (GPU) con 2Gb de RAM dedicada. Como punto final indicaré que es un portátil, por lo que las gráficas siempre van un poco más "capadas" que las normales.

Instalar *nvtop*:

```
sudo snap install nvtop
```

Después, antes de continuar verifiqué el estado de la GPU, para ello consulté si realmente tenía una Nvidia por algún lado:

```
lspci | grep -i nvidia
```

Después comprobé si encontraba la gráfica (parece obvio pero en algunas de las pruebas desapareció):

```
sudo lshw -c display
```

Y por último comprobé si tenía *Cuda* instalado (pero no, al principio no estaba instalado):

```
nvidia-smi
```

Una vez revisada la información y tras haber leído la documentación, lo primero que había que abordar era hacer desaparecer el driver `nouveau` para evitarnos problemas:

```
sudo apt purge xserver-xorg-video-nouveau
```

Después lo pusimos en la *blacklist* y la desactivamos, para ello editamos el fichero `/etc/modprobe.d/blacklist.conf` y añadimos las siguientes líneas:

```
blacklist nouveau
options nouveau modeset=0
```

Y para hacerlo efectivo:

```
sudo update-initramfs -u
```

> La preparación siempre hay que hacerla después de cada nueva instalación, dando por supuesto que limpiamos las instalaciones anteriores.

Reiniciamos el ordenador.

(5/3/2024) ACTUALIZACION: 
 Una vez reiniciado, cambie a un terminal sin interfaz gráfica utilizando la combinación de teclas CTRL+ALT+F2, seguidamente desactive la interfaz gráfica escribiendo `sudo telinit 3`

[-^-](#index)
## Método 1: Instalar desde los repositorios de *Neon*<a name="chapter-1b"></a>

Lo primero que hice fue decidir qué driver quería utilizar, opté por la versión 535 (el último disponible):

```
sudo apt install nvidia-driver-535
```

Posteriormente instalé el *applet* de la barra de tareas, *Cuda* y varios paquetes necesarios:

```
sudo apt install plasma-optimus primus-vk-nvidia nvidia-cuda-toolkit-gcc cuda-drivers-fabricmanager-535 primus-nvidia
```

El paso siguiente fue reiniciar el sistema para que se activaran los nuevos drivers.

Una vez inicializado, tuve que "obligar" a que se pusiera a trabajar el *applet* (a veces tardaba 30 segundos, otras veces no aparentaba arrancar).

> Para "obligar" a leer la *Nvidia* puedes ejecutar un `sudo modprobe nvidia_modeset`, con ello la activas.

A continuación seleccioné el icono de *Plasma-optimus* para lanzar el "Switch to Nvidia GPU" (tras aceptar el mensaje el sistema se reinicia).

> Incluso después de configurar todo correctamente había veces que se quedaba medio 'lela' y tenía que cambiar a la integrada de Intel y después volver a la GPU dedicada.

**Todavía no hemos terminado, falta la configuración, que está después de explicar el otro método de instalación.**


[-^-](#index)
## Método 2: Utilizar los instaladores de *Nvidia*<a name="chapter-1c"></a>

Después de reinstalar la iso para probar desde cero, y además preparar el sistema como ya hemos indicado, pasamos a realizar la instalación.

Primero descargamos la versión, en este caso hemos optado por la última: la 545. Como indiqué arriba, descargada de [NVIDIA](https://www.nvidia.com/es-es/geforce/drivers/). Es curioso que *nvidia* tiene dos páginas para descargar, [la otra](https://www.nvidia.es/Download/index.aspx?lang=es) te propone la versión 535. Curioso.

Una vez descargada, y tras documentarnos; vemos que necesitamos tener instalado `pkg-config`:

```
sudo apt install pkg-config
```

> Necesitamos este paquete e indicarle también al instalador la ruta.

Una vez terminado, procedemos a ejecutar el instalador indicandole la ruta del `glvnd-egl-config-path`:

```
sh NVIDIA-Linux-x86_64-545.29.06.run --silent --glvnd-egl-config-path=/usr/lib/x86_64-linux-gnu/
```

Una vez terminada la instalación, comprobamos que está correcta:

```
sh NVIDIA-Linux-x86_64-545.29.06.run --sanity
```

Y verificamos las versiones:

```
sh NVIDIA-Linux-x86_64-545.29.06.run --driver-info
```

El siguiente paso es instalar *Cuda*, para ello descargamos el instalador:

```
wget https://developer.download.nvidia.com/compute/cuda/12.3.2/local_installers/cuda_12.3.2_545.23.08_linux.run
```

> Cuatro *insignificantes* gigas (más que mi distro).

Atendiendo a la documentación, procedemos a preparar el sistema instalando los *headers* de mi *kernel* y borrando la key desfasada:

```
sudo apt-get install linux-headers-$(uname -r)
sudo apt-key del 7fa2af80
```

Ahora a instalar *Cuda*:

```
sudo sh cuda_12.3.2_545.23.08_linux.run
```

> Como anteriormente hemos instalado los drivers de *Nvidia*, ahora nos toca desmarcarlos del instalador, ya que de lo contrario tendremos un error y no podremos continuar; no marco nada más, ya que no es pertinente para mi arquitectura. Evidentemente, hago caso omiso al mensaje que se presenta advirtiendo que *no* se ha pedido instalar el driver.

El siguiente paso es terminar de configurar las rutas de la instalación.

Añadimos a `$HOME/.bashrc` las siguientes rutas:

```
export PATH=/usr/local/cuda-12.3/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-12.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
```

y releer las preferencias para activarlas:

```
source ~/.bashrc
```

Ahora añadimos persistence-daemon para que arranque al inicio del sistema. Añadimos al archivo `/etc/profile.d/99-nvidia-config.sh` 

```
/usr/bin/nvidia-persistenced --verbose
```

Por último, instalamos el *applet* para poder activar la GPU:

```
sudo apt install plasma-optimus
```

---

[-^-](#index)
# Configuración (apto para ambos métodos de instalación)<a name="chapter-2"></a>

Para los dos métodos deberemos terminar con la configuración de la GPU para que sea convenientemente reconocida.

[-^-](#index)
## Configurar *Cuda*<a name="chapter-2a"></a>

Configuramos *Cuda* añadiendo al archivo `/etc/profile.d/99-cuda-config.sh` las siguientes líneas:

```
export CUDA_HOME=/usr/local/cuda
export CUDA_PATH=$CUDA_HOME/lib
export CUDA_DEVICE_ORDER="PCI_BUS_ID"
```

Además, debemos indicar cuál es la posición de la GPU, en mi caso es la "1". Puedes comprobarlo fácilmente con `nvtop`, viendo si la Nvidia es el *Device* 0, 1, 2, etc.:

```
export CUDA_VISIBLE_DEVICES=1
```

> En esta variable podemos indicar tantas GPU como estén disponibles para *Cuda*.

Y si queremos que *Cuda* utilice la memoria *Swap*, entonces tendremos que agregar lo siguiente:

```
export CUDA_DEVICE_ALLOW_GROWTH=1
```

> Hago notar que Torch necesita al menos 12Gb de RAM, si la GPU no los tiene disponibles no funcionará, de ahí la importancia de poder acceder a memoria externa a la GPU. Ni qué decir que pretender trabajar con la memoria *Swap* es una burrada.


[-^-](#index)
## Configurar NVIDIA<a name="chapter-2b"></a>

Revisamos el archivo `/etc/modprobe.d/nvidia-graphics-drivers-kms.conf` y revisamos si existe lo siguiente:

```
options nvidia-drm modeset=1
```

Y si queremos que NVIDIA utilice la memoria *Swap*, entonces tendremos que agregar lo siguiente:

```
options nvidia_uvm allow_sw_pages=1
```

[-^-](#index)
# Terminar la instalación<a name="chapter-3"></a>

Ya es momento de reiniciar por última vez. En la documentación de *Cuda* aconsejan que te bajes un repo de ejemplo y que compruebes que funciona.

A mi, el método de instalación que más estabilidad me ha dado es instalar descargando los *drivers* de la web de *Nvidia*.

---

Espero te haya servido de ayuda.
:)