[備忘録]Ubuntu22.04で急にCudaが使えなくなった際の対処

この手の記事はn番煎じかもしれませんが、勉強 and 備忘録のためにpytorchでcudaを使用できるようにするまでにやったことをまとめます。
# 環境と状況
* Ubuntu 22.04
* 数ヶ月ぶりににPytorchでcudaを使用しようとしたらエラー（その間何度がアップデート）

# 現状確認
まず、定番の``nvidia-smi``コマンドでGPUが認識されているかを確認。以下の出力が得られた。

```
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. 
Make sure that the latest NVIDIA driver is installed and running.
```
ということで、NVIDIA driver の再インストールが必要になりそう。以下の記事を参考にし、再インストールを試みる。

https://qiita.com/kiwsdiv/items/3e8dac099cb27c7c4b01#%E5%A4%B1%E6%95%97-nvidia-driver%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E5%BE%8C%E3%81%ABenroll-mok%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%9B%E3%81%9A%E3%81%AB%E5%86%8D%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%9F

# ケース1：デバイスドライバを新たにinstallして解決
`nvidia-smi`コマンドを実行すると、`Make sure that the latest NVIDIA driver is installed and running.`（最新のドライバーが動いているかをチェックしろ）と言われたので、基本的には以下の記事を参考にして、新しいドライバーを入れなおすことを試みた。

https://qiita.com/y-vectorfield/items/72bfb66d8ec85847fe2f

まず、APTのリポジトリにPPAを追加する。APTはLinuxに搭載されているパッケージ管理ツールであり、ソフトウェアのダウンロードやインストールを自動で行えるようにするものである。

リポジトリとは、ソフトウェアやドライバを保存・配布する場所を指す。**PPA（Personal Package Archive**は、特定の個人やチームが作成した特別なリポジトリである。PPAを追加することで、通常のリポジトリにはない新しいソフトウェアや最新バージョンが利用可能となる。

たとえば、**graphics-drivers/ppa**というPPAは、NVIDIAの最新グラフィックスドライバーがまとまっているリポジトリである。このPPAを追加すると、常に最新のNVIDIAドライバーがインストールできるようになる。

手順
1. リポジトリにPPAを追加する。
2. sudo apt update コマンドを実行してリポジトリ情報を更新する。
3. その後、NVIDIAドライバーなどのインストールが可能となる。

```
# リポジトリの追加
sudo add-apt-repository ppa:graphics-drivers/ppa
# リポジトリのアップデート
sudo apt update
```
`ubuntu-drivers devices`コマンドは、システムにインストール可能なドライバーの一覧を表示するためのコマンドである。これで、必要かつインストール可能なドライバーを表示。
```
ubuntu-drivers devices
```
上記コマンドを実行すると以下の出力が得られる。
```
modalias : pci:v000010DEd00002487sv000010DEsd00001530bc03sc00i00
vendor   : NVIDIA Corporation
driver   : nvidia-driver-535-server - distro non-free
driver   : nvidia-driver-470-server - distro non-free
driver   : nvidia-driver-535-open - distro non-free
driver   : nvidia-driver-565 - third-party non-free recommended
driver   : nvidia-driver-550-open - third-party non-free
driver   : nvidia-driver-520 - third-party non-free
driver   : nvidia-driver-550 - third-party non-free
driver   : nvidia-driver-515 - third-party non-free
driver   : nvidia-driver-560 - third-party non-free
driver   : nvidia-driver-555 - third-party non-free
driver   : nvidia-driver-470 - distro non-free
driver   : nvidia-driver-535-server-open - distro non-free
driver   : nvidia-driver-560-open - third-party non-free
driver   : nvidia-driver-545-open - distro non-free
driver   : nvidia-driver-555-open - third-party non-free
driver   : nvidia-driver-545 - third-party non-free
driver   : nvidia-driver-535 - third-party non-free
driver   : nvidia-driver-525 - third-party non-free
driver   : nvidia-driver-565-open - third-party non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

```
この中で`recommended`と記載されている、`nvidia-driver-565`をドライバーとして使用する。これは、サードパーティ（公式ではないけれど、関連する外部の提供元）から提供された、non-free（クローズド）なドライバーである。以下のコマンドでinstallする。

```
sudo apt install -y nvidia-driver-565
```

その後、`nvidia-smi`コマンドを実行すると、以下の出力が得られ、GPUが使用できるようになった。

```
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 565.57.01              Driver Version: 565.57.01      CUDA Version: 12.7     |
|-----------------------------------------+------------------------+----------------------+
| 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 GeForce RTX 3060        On  |   00000000:01:00.0 Off |                  N/A |
| 30%   33C    P0             37W /  170W |       2MiB /  12288MiB |      2%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
                                                                                         
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+

```

# ケース2：GPUが抜けていた
以後記載しているのは、頑張って原因を探ったものの結果的に**GPUがしっかりささっていなかった**という場合の試行錯誤である。（一番最初に最もシンプルな部分を調べることが重要だと感じた）

## 既存NVIDIAドライバのアンインストール
既存のドライバーをアンインストールするために、以下のコマンドを実行。

```
sudo apt-get --purge remove nvidia-*
```
その結果、以下の出力が得られた。

```
E: パッケージ nvidia-system-monitor-qt が見つかりません
```
以前はCudaが動いていたので、何かしらは残っているはず、、
一旦、APTのパッケージリストにNVIDIA関連のものが認識されているかを確認する。以下コマンドで、nvidia関連のパッケージがそもそも存在するかを確認してみる。

```
dpkg -l | grep nvidia
```
すると多数のnvidiaパッケージがちゃんと存在していることがわかった。これはワイルドカードが認識されていないことが原因なのではと考え、以下のようにコマンドを修正し実行すると、すべてパッケージが消去された。

```
sudo apt-get --purge remove "nvidia-*"
```
その後、``sudo apt autoremove``により、依存関係のなくなったパッケージもすべて自動削除した。その後、上記記事に従い、``nouveau``をブラックリストに入れる。（この意味は本記事最後の「ここから得られる知識」を参照）以下コマンドでnouveauが機能しているかを確認。

```
lsmod | grep nouveau
```

その結果、自分の環境にnouveauはなかったことが判明したが、一応記事に忠実に従い、以下のコマンドを実行。

```
sudo sh -c "echo 'blacklist nouveau' > /etc/modprobe.d/blacklist-nouveau.conf"
sudo sh -c "echo 'options nouveau modeset=0' >> /etc/modprobe.d/blacklist-nouveau.conf"
sudo update-initramfs -u
sudo reboot
```
## NVIDIA ドライバのインストール
再度記事に従って、NVIDIAドライバのインストールを進めていく。下記コマンドを実行。

```
# リポジトリの追加
sudo add-apt-repository ppa:graphics-drivers/ppa
# パッケージリストの更新
sudo apt update
```
ところが、``$ ubuntu-drivers devices``をコマンド入力してもデバイス一覧が表示されない。dkpgコマンドで確認してみると、nvidia関連のパッケージとcuda関連のパッケージがまだ残っていたので、``dkpg -l`` で完全に出力されなくなるまで完全にアンインストールしてみた。やはり、何も表示されない。

そもそもデバイスが認識されていないのではと考え、以下のコマンドを実行してみる。
```
lspci | grep -i nvidia
```
すろとそもそもPCIリストにGPUが含まれていないことが判明。ハードウェアレベルで何か問題がある可能性、、

その後、PCIスロットを確認してみたところ、GPUがちゃんと刺さっていないことが判明した。*灯台下暗し*

# ここから得られる知識
* dpkg：
Debian packageの略であり、パッケージの追加、削除、情報提供などを行うパッケージ管理ソフト。実際に使用する際はAPTなどの高レベルなツールによって使用される。``dkpg -l`` でインストールされているパッケージの一覧を確認することが可能。

* nouveau(ヌーヴォー)
    * NVIDIAグラフィックカードのオープンソースドライバー。NVIDIAは自社ドライバを配布しているが、ユーザーは自由に改良することができない。
    * nouveauはOSSなので、誰でも改善に参加することができるものの、NVIDIA公式のドライバと競合することも多々あるらしい。

* ブラックリスト
    * 特定のハードウェアやソフトウェアをOSが使用しないようにするためのリスト
    * 通常 /etc/modprobe.d/ ディレクトリ内の設定ファイルに記述
    * ここにパッケージなどを追加することで、指定されたアイテムのシステムによるロードを防止
    * 今回はnouveauをここに追加し、NVIDIAのドライバが正しく動くようにする

* lspci
    * LinuxシステムでPCIデバイスのリストを表示するコマンド

* PCIリスト
    * PCI（Peripheral Component Interconnect）
    * コンピュータのマザボ上のスロットを介して追加のハードウェアコンポーネント（グラフィックカード、ネットワークカード、サウンドカードなど）を接続するための標準的なインターフェース

* BIOS
    * Basic Input and Output Systemの略でマザボに内臓されたファームウェア
    * コンピュータの電源が入ると自動で起動 → ハードウェアの初期化とOSの起動を実行
    * OSが入っていない状態でのPCの設定を行える

* UEFI
    * 基本的な役割はBIOSと一緒だが提供する機能が高度化
    * BIOSの機能にGUIを追加
    * 大容量ハードウェアを使用できるようになり、インターネット経由でOSをロード(PxEブート)可能なものもある

* ファームウェア
    * ハードウェアデバイスの基本的な制御と管理を行うためのソフトウェアプログラム
    * ハードウェアデバイスの永続的なメモリ(非揮発性メモリ)に組み込まれているため、家電やPCなど様々なデバイスで使用
    * 独立して動作するため、OSや他のソフトウェアなどは必要ない
    * ハードウェアに対して特別に設計されるものなので、ハードウェア依存