TensorFlowのGPU環境セットアップの個人的決定版 (ubuntu 16.04)

2018/2/9 修正

## 1.目的
tensorflowが1.5からcuda9に対応したので，それ用の環境設定をする．
GPU周りの環境設定が割と面倒臭いので，`.sh`にまとめた．

今までnvidiaのサイトから`.run`を落としてきて，それからインストールしていたが，一回ブラウザを開いたりNVIDIAのdeveloperにログインしたりと手間だったので，全て`apt-get`で入るやり方を試した．

前のメモ（[GPUを使えるようにする for tensorflow](https://qiita.com/kazetof/items/941c3463ac452b496d59)）もあるが，その決定版（暫定）という感じ．前のやつはエラー対応みたいなところを今後も載っけていく予定．

## 2.環境
- OS : ubuntu desktop 16.04 LTS
- CPU : Intel(R) Xeon(R) CPU E5-4640 v3 (x86_64)
- GPU : GeForce GTX 1060

## 3.インストールするもの
- cuda 9.0
- cudnn7
- NVIDIA driver version 390.12

最初cuda9.1を入れたけど，cuda9.0の色々がないぞと怒られ，symlinkでなんとかしようと思ったが数も多いしやめた．
普通にcuda9.0にダウングレードするのが良さそう．

https://github.com/tensorflow/tensorflow/issues/15656
この辺を見ても，少なくともtensorflow1.5, 1.6の間はcuda9.0の方が良さそうだ．

## 4.インストールの準備
~~NVIDIA Driverのrunファイルのダウンロード．~~
~~http://www.nvidia.com/Download/index.aspx~~
~~ここから自分のGPUのdriverの`.run`を落として次に出てくる`gpu_setup.sh`と同じディレクトリにおく．~~
全て`apt-get`で入れるようにしたため不要．

## 5.インストール
とりあえずコードはこんな感じで，これを`sudo`なしで`./gpu_setup.sh`で多分いける．

```bash:gpu_setup.sh
# run without sudo.

###############
# CUDA
###############
# refference
## http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#pre-installation-actions
### 3.6. Ubuntu
#### 1.Perform the pre-installation actions.
sudo apt-get install linux-headers-$(uname -r)

#### 2.Install repository meta-data
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.0.176-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1604_9.0.176-1_amd64.deb

#### 3.Installing the CUDA public GPG key
sudo apt install gnupg-curl
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub

#### 4.Update the Apt repository cache
sudo apt-get update

#### 5.Install CUDA
# sudo apt-get install cuda-9-0
sudo apt-get install cuda-toolkit-9-0

### 4.3. Disabling Nouveau
echo "blacklist nouveau" | sudo tee --append /etc/modprobe.d/blacklist-nouveau.conf
echo "options nouveau modeset=0" | sudo tee --append /etc/modprobe.d/blacklist-nouveau.conf
sudo update-initramfs -u

### 7. Post-installation Actions
echo "# cuda" | sudo tee --append ~/.profile
echo "export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}" | sudo tee --append ~/.profile
echo "export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" | sudo tee --append ~/.profile

sudo cp ./nvidia-persistenced.service /usr/lib/systemd/system/
sudo systemctl enable nvidia-persistenced

################
# NIVIDA driver
################

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-drivers_390.12-1_amd64.deb
sudo dpkg -i cuda-drivers_390.12-1_amd64.deb
sudo apt-get update
sudo apt-get install nvidia-390 nvidia-390-dev libcuda1-390 nvidia-modprobe nvidia-settings nvidia-opencl-icd-390

# for nvidia-smi
echo "export PATH=/usr/lib/nvidia-390/bin${PATH:+:${PATH}}" | sudo tee --append ~/.profile
source ~/.profile

########
# cudnn
########

wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64/libcudnn7_7.0.5.15-1+cuda9.0_amd64.deb
sudo dpkg -i libcudnn7_7.0.5.15-1+cuda9.0_amd64.deb
sudo apt-get update
sudo apt-get install libcudnn7
```

## 6.補足
### 6.1 cudnnのインストールについて
`cudnn`は[NVIDIA cuDNN](https://developer.nvidia.com/cudnn)にアカウント作ってログインしてダウンロードしないといけないが，[cuDNN 5.1をapt-getでUbuntu 16.04 LTSにインストールしてみた](https://soralab.space-ichikawa.com/2017/04/cudnn51-install/)ここでDIGITSの方から落とすという革命を起こしている人がいたので真似させてもらった．

### 6.2 NVIDIA driverのインストールについて
~~本当はNVIDIA Driverも同様にやりたかったが，`apt-get`で`390.12`を入れて適当にkerasのexampleを回すと，`/proc/driver/nvidia`がないぞと怒られたりした．~~
`.run`でインストールすると，`/proc/driver/nvidia`以下にNVIDIA Deriver（ここでは`nvidia-390`）を配置するが，`apt-get`で入れると，`/usr/lib/`に配置する．

~~他にも`nvidia-smi`コマンドが一緒に入らなかったので，`.run`で裏でよしなにやってくれているらしいのでこれを使うのがいいかなという結論に至った．~~
`apt-get`で`nvidia-390`をインストールした際に，一緒に`nvidia-smi`も入れているが，パスを通してくれていなかった．
`nvidia-smi`コマンド自体は`/usr/lib/nvidia-390/bin`にあったので，パスを通せば使えた．


~~(というかそもそも`nvidia-smi`がdriverのインストール時に入るのも謎な気もする．cuda toolkitを入れるときに一緒に入ってくれる方が自然なような．)~~
実際ドライバのダウンロード時に入っていたし，まあそういうものかと受け入れた．

## 7.疑問
NVIDIA driverのインストール時に，lightdmやGUIに影響を及ぼして，GUIにログインできなくなったり，ログインしても画面が真っ暗なままになるのはどういう可能性が考えられるか誰か教えてください...

今回の僕の場合は，`apt-get`で`390.12`を入れたあとに`.run`でNVIDIA driverを入れたときに，ログイン画面周りやGUI周りが起動しなくなった．
apt-getで入れたconfigと`.run`のconfigが競合したのではないかと思うのだが，結局OSのクリーンインストールで直してしまった．

仕組みはいまいちわかっていないが，とりあえず教訓としては，NVIDIA driverの`.run`を実行する前に，

```console
$ dpkg -l | grep nvidia
```
をやってみて，すでにドライバーが入っている場合は，

```console
$ sudo apt-get remove --purge nvidia-*
```
あたりでちゃんと`--purge`オプションをつけて消すのが良さそう．

もしくはNVIDIAが準備してくれてる

```console
$ sudo nvidia-uninstall
```
これでもおそらくいいのではと思われる．~~（試してない）~~

試したが，`.run`で入れたときは，`sudo nvidia-uninstall`コマンドでアンインストールする．
`apt-get`で入れたときは，上の`sudo apt-get remove --purge nvidia-*`で消すようだ．

### 解決
下記コメントより@Lirimy さんに色々と教えてもらって解決しました．圧倒的感謝です．

まず，
https://github.com/NVIDIA/DIGITS/blob/digits-5.0/docs/InstallCuda.md#deb-packages
> apt-get install cuda - This will install the latest toolkit (currently 7.5) and the latest driver (currently nvidia-352).

とあるように，cudaを入れたときにバージョンの異なるNVIDIA deriverが入り，deb -> apt-getで自分が入れたいバージョンのNVIDIA deriverを入れようとしたときには，

http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#handle-uninstallation
> ![Screen Shot 2018-02-09 at 14.42.26.png](https://qiita-image-store.s3.amazonaws.com/0/164264/2580115b-17fb-9d96-fc5b-9160cde0f895.png)

このようにもともとdebで入れたdriverのバージョンと，これからdebで入れようとしているドライバーのバージョンが食い違っていると，何もしないという挙動になり，結果として正しいドライバーが入っていなかったようだ．

[5.インストール](https://qiita.com/kazetof/items/c2f8b2751d3ed9600a57#5%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)のコードでは，cuda toolkitのインストールとdriverのインストールを分けて対応した．



## 8.参考
cudaのインストールはこれを必ず参照するという結論に至った．
http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#pre-installation-actions

NIVIDAの準備してくれてるレポジトリ（この辺から落とすと便利）
https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/
http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64/

今回は使っていないが，`.run`で入れるときの参考
https://gist.github.com/wangruohui/df039f0dc434d6486f5d4d098aa52d07