Ubuntu16.04にCUDA8.0とChainerをインストールする


CUDA Toolkitを管理する方法として[nvidia-docker](https://github.com/NVIDIA/nvidia-docker)を使うという手段がありますが、今回はこれを用いず直接CUDA Toolkitをインストールしました。

# 環境
* Ubuntu16.04 64bit
* Core i5
* GeForce 940M

# 用意するもの
1. [CUDA toolkit](https://developer.nvidia.com/cuda-release-candidate-download)
2. [cuDNN](https://developer.nvidia.com/cudnn)
3. [ドライバ](http://www.nvidia.com/Download/index.aspx?lang=en-us) (自分の環境に合わせて適切に選択)

CUDA Toolkitのインストールにはrunfile(cuda_8.0.44_linux.run)を用いました。
![cuda-toolkit.png](https://qiita-image-store.s3.amazonaws.com/0/46932/8c1d3010-c494-b2ca-885c-f3b5b9d018b6.png)


# インストール手順
## 1. ドライバをインストールする
セキュアブートが有効になっている場合は、あらかじめ無効にしておいてください。
Ctrl+Alt+F1でtty1に移動して、nvidia-smiコマンドとドライバをインストールします。
途中でX11の設定を書き換えるかどうかを聞かれます。書き換えると画面が映らなくなったりするので、書き換えないことをおすすめします。
インストールが終わったら一度再起動してください。

```
sudo service lightdm stop  # X11を落とす
sudo ./NVIDIA-Linux-x86_64-<version>.run  # nvidia-smiコマンドがインストールされるはず
sudo reboot
```

`nvidia-smi`コマンドの出力がこんな感じになっていれば、GPUを検出できています。

```
$nvidia-smi                           
Mon Aug 15 15:31:22 2016       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 361.77                 Driver Version: 361.77                    |
|-------------------------------+----------------------+----------------------+
| 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 940M        Off  | 0000:01:00.0     Off |                  N/A |
| N/A   59C    P0    N/A /  N/A |    254MiB /  2003MiB |      8%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0      4105    G   /usr/lib/xorg/Xorg                             165MiB |
|    0      4988    G   fcitx-qimpanel                                   7MiB |
|    0      5310    G   ...ves-passed-by-fd --v8-snapshot-passed-by-    67MiB |
|    0      5598    G   ...DocWrittenScriptsInMainFrame --force-fiel    13MiB |
+-----------------------------------------------------------------------------+
```

もし不安定な場合は`apt-get`でドライバをインストールすると動くかもしれません。しかしシステムがX11をGPUで動かそうとしてX11の動作が不安定になるためおすすめはしません。

```
sudo apt-get install nvidia-361
sudo reboot
```

## 2. CUDA toolkitをインストールする
tty1で次のコマンドを実行します。
__注意: runfile実行時にドライバをインストールするか聞かれますが、ここではインストールしないでください。__

```
sudo service lightdm stop
sudo ./cuda_8.0.44_linux.run --override  # 注意: ドライバはここではインストールしない
```

Ubuntu16.04ではgccのバージョンがCUDAの推奨するものと違っているようですが、`--override`オプションをつけてToolkitを無理矢理インストールしました。
インストールが正常に行えていれば`/usr/local/cuda-8.0`が存在しているはずです。

もしChainerを動かす際にうまくいかないのであれば、gcc5.2をインストールしてから再度

```
sudo service lightdm stop
sudo ./cuda_8.0.44_linux.run  # 注意: ドライバはここではインストールしない。gcc5.2をあらかじめインストールしておく。
```

としてください。

## 3. cuDNNをインストールする
[cuDNN]を展開してファイルをコピーします。

```
tar xvf cudnn-8.0-linux-x64-v5.1.tgz
sudo cp cuda/include/* /usr/local/cuda-8.0/include
sudo cp cuda/lib64/* /usr/local/cuda-8.0/lib64
```

`.bashrc`にこれを追記し、`source ~/.bashrc`してください。

```
export CUDA_PATH=/usr/local/cuda-8.0
export PATH=$CUDA_PATH/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_PATH/lib64:$LD_LIBRARY_PATH

export CPATH=$CUDA_PATH/include:$CPATH
export LIBRARY_PATH=$CUDA_PATH/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$CUDA_PATH/lib64:$LD_LIBRARY_PATH
```

## 4. Chainerをインストールする
ふつうにpip3で入れます。

```
sudo pip3 install chainer
```

## 5. 動作チェック
`import cupy`が通れば成功です。

```
$python3
>>> import cupy
```

Chainerのソースコードに同梱されているMNISTのサンプルも動きます。

```
git clone git@github.com:pfnet/chainer.git
cd chainer/examples/mnist     
python3 train_mnist.py --gpu=0
```

## 6. カーネルのアップデートについて
カーネルがアップデートされるとドライバにアクセスできなくなります。
新しいカーネルがインストールされた際には1のドライバのインストールをやり直してください。