Ubuntuでnvidiaドライバーが動作しない

HDDが壊れたので新しくSSDを買ってUbuntuを入れ直して、CUDAを入れたが、インストールされたNVIDIAドライバーがうまく動作せず、nvidia-smiを打つとこのようなメッセージが出て困った
  
```
$ nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running."
```

結論としては、Ubuntuの最新カーネルではnvidiaドライバが機能しないトラブルが起きているようなので、ubuntuカーネルを古いものに変えると正常になった。  

## 環境
* Ubuntu 16.04
* GTX 1080
* CUDA 8.0

## 一応作業手順

```
$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
$ sudo apt-get update
$ sudo apt-get install cuda
$ sudo init 6
```

これでcuda-toolkitとnvidia-387が自動でインストールされて、以前なら問題なく動作していた。  
しかしnvidiaドライバにアクセスできない、ドライバが合ってないみたいなことを言われて困った。
起動時も解像度が合っておらず、うまくドライバが読み込めていない模様。

```
$ nvidia-smi
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ドライバのバージョンが違う？と思い、[nvidiaのサイト](http://www.nvidia.co.jp/Download/index.aspx?lang=jp)で対象GPUのドライバのバージョンを確認してみる。  
GTX1080だと384と出たので、nvidia-387を削除してnvidia-384を入れようと試みる。  
  
削除するときは、

```
$ sudo apt-get --purge remove nvidia-*
$ sudo apt-get --purge remove cuda-*
```

で削除する。一応関連するものが残っていないか以下で確認し、残っていたら個別に削除する。

```
$ dpkg -l | grep nvidia
$ dpkg -l | grep cuda
```

でnvidia-384を入れる

```
$ sudo apt-get install nvidia-384
```

これならば、nvidia-smiが通る。
しかしCUDAパッケージはnvidia-387に依存しているかつnvidia-384を入れるとnvidia-387が削除されるので、CUDAは削除されてしまう。  

## 解決方法
似たような状況になっている人がいないか調べたところ、ここ数日で同じ状況に遭遇している人がそこそこいた。  

[NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver" Ubuntu 16.0...](https://devtalk.nvidia.com/default/topic/1000340/cuda-setup-and-installation/-quot-nvidia-smi-has-failed-because-it-couldn-t-communicate-with-the-nvidia-driver-quot-ubuntu-16-04/1)

どうやら、Ubuntu16.04のカーネルが最近4.10から4.13に変わり、環境を新しくした場合にnvidia-ドライバがうまく働かない状況になっている模様。  

そこで暫定的に、PC起動時にESCキーを押してブート選択メニューに入り、Advanced Option for Ubuntuを選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/50474/3793af7c-f1f3-8b0c-259b-dd6bb7b8213a.png)

デフォルトでは4.13.26になっていたが、前の4.10.28があったのでそれを選択して起動する。
画像は借り物なのでバージョンが違うので注意。  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/50474/a486a421-19bb-9ca8-53aa-5899b1ab66b0.png)

すると解像度も正常になり、nvidia-smiもちゃんと返ってくるようになった

```
$ nvidia-smi
Sat Jan 13 14:05:15 2018       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 387.26                 Driver Version: 387.26                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1080    Off  | 00000000:01:00.0  On |                  N/A |
| 55%   82C    P2   146W / 180W |    842MiB /  8111MiB |     98%      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 1080    Off  | 00000000:03:00.0 Off |                  N/A |
| 48%   67C    P2   166W / 198W |    783MiB /  8114MiB |     99%      Default |
+-------------------------------+----------------------+----------------------+
|   2  GeForce GTX 1080    Off  | 00000000:04:00.0 Off |                  N/A |
| 48%   67C    P2   185W / 198W |    783MiB /  8114MiB |     98%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
```

## 起動時のデフォルトカーネルを変更
さすがに再起動のたびに毎回カーネルを変更するのは面倒なので、デフォルトで設定しておく。  

まずはGRUBの起動オプションの確認をする。

```
$ grep menuentry /boot/grub/grub.cfg
```



```
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-e0077458-0564-44fa-8774-8de1e30bfe34' {
submenu 'Advanced options for Ubuntu' $menuentry_id_option 'gnulinux-advanced-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.13.0-26-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.13.0-26-generic-advanced-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.13.0-26-generic (upstart)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.13.0-26-generic-init-upstart-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.13.0-26-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.13.0-26-generic-recovery-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.10.0-28-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.10.0-28-generic-advanced-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.10.0-28-generic (upstart)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.10.0-28-generic-init-upstart-e0077458-0564-44fa-8774-8de1e30bfe34' {
	menuentry 'Ubuntu, with Linux 4.10.0-28-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.10.0-28-generic-recovery-e0077458-0564-44fa-8774-8de1e30bfe34' {
```
これは起動時にESCキーを押して入った起動メニューと対応している。

デフォルトでどのオプションで起動するかは、``/etc/default/grub``にかかれている。

```
GRUB_DEFAULT=0
```
これだと、トップメニューの0番目、Ubuntuを選ぶようになる。  

この部分を以下のように変更する。  

```
GRUB_DEFAULT="Advanced options for Ubuntu>Ubuntu, with Linux 4.10.0-28-generic"
```

確認していないが、おそらく以下でもOK

```
GRUB_DEFAULT="1>3"
```

2番目(Advanced options for Ubuntu)を選択→3番目(Ubuntu, with Linux 4.10.0-28-generic)を選択みたいな感じ。  

GRUBの設定を反映させるために、以下を実行  

```
$ sudo update-grub
```


その後、再起動して、使用カーネルを確認すると、4.10.28になっていた。  

```
$ uname -r
4.10.0-28-generic
```


## 参考

http://sweng.web.fc2.com/ja/linux/ubuntu/change-default-boot-kernel.html

https://askubuntu.com/questions/216398/set-older-kernel-as-default-grub-entry