GPUを使えるようにする for tensorflow

# はじめに
2018/2/8追加
[TensorFlowのGPU環境セットアップの個人的決定版 (ubuntu 16.04)](https://qiita.com/kazetof/items/c2f8b2751d3ed9600a57)）に今の所これが良いのではという暫定版メモを書きました．

# 1.GPUの確認
GPUを計算に使いたいなーと思い，Centos7に環境を導入した．目標はtensorflowというかkerasの計算をGPUでできるようにすること．

```shell
$ lspci | grep VGA
01:00.0 VGA compatible controller: NVIDIA Corporation GK208 [GeForce GT 710B] (rev a1)
```

http://blog.amedama.jp/entry/2017/03/13/123742
この記事によると，Compute Capabilityが3.0以上でないと現在普及しているCUDA8.0に対応していないそうだ．
このGPUは超絶古いやつだが，Compute Capabilityが3.5なのでギリいけそう．

# 2.KerasでGPUを使うのに必要なもの
http://blog.amedama.jp/entry/2017/02/26/120215
この記事によると以下の3つをダウンロードすれば良い．

- CUDA
- cuDNN
- TensorFlow-gpu

# 3.CUDAのインストール
nvidiaの以下のdocumentに従った．
http://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#axzz4l4RhQh5L

まずは環境の確認から．

```shell
$ python --version
# Python 3.5.2 :: Anaconda 4.2.0 (64-bit)
```

```shell
$ uname -m && cat /etc/*release
# CentOS Linux release 7.3.1611 (Core) 
```

```shell
$ gcc --version
# gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
```

```shell
$ uname -r
# 3.10.0-514.10.2.el7.x86_64
```

どれも上記のURLのsystem requirements を満たしている．

というわけでcudaをインストールする．
https://developer.nvidia.com/cuda-downloads

![Screen Shot 2017-06-26 at 12.41.07.png](https://qiita-image-store.s3.amazonaws.com/0/164264/fb6381c3-2c5b-90df-269c-12b3d29f8809.png "Screen Shot 2017-06-26 at 12.41.07.png")

上図のようにbase installerをcuda-downloadsにある通り以下のコマンドを実行してインストールできた．

```shell
sudo rpm -i cuda-repo-rhel7-8.0.61-1.x86_64.rpm
sudo yum clean all
sudo yum install cuda
```

# 4.cuDNNのインストール
次にcuDNNをインストールする．
https://developer.nvidia.com/developer-program
ここでdeveloper アカウントを作成して，
https://developer.nvidia.com/rdp/cudnn-download
ここでcuDNNをダウンロードする．linuxのcuda-8.0 versionをダウンロードした．

```shell
$ tar -xvzf cudnn-8.0-linux-x64-v5.1.tgz 
```

ここで展開したものは```/usr/local/cuda```と，```/usr/local/cuda-8.0```の各include, lib64ディレクトリに移動した．詳細は6.1を参照．

他の記事を参考に以下のpathを追加したが，余計なものも入ってるかも．

```.bash_profile
# CUDA path
export CUDA_ROOT="/usr/local/cuda"
export LIBRARY_PATH=$CUDA_ROOT/lib:$CUDA_ROOT/lib64:$LIBRARY_PATH  
export LD_LIBRARY_PATH=$CUDA_ROOT/lib64/
```

```
source ~/.bash_profile
```

# 5.tensorflow-gpuのダウンロード

```
$ pip install tensorflow-gpu
```

# 6.1.libcudnn.so.5が見つからないエラー

```
In [2]: import keras
(import tensorflowでも)
ImportError: libcudnn.so.5: cannot open shared object file: No such file or directory
```

もともとcudaを保存しているディレクトリが```/usr/local/cuda```にあった．そこにcuDNNを移動する．```/usr/local/```以下には，```cuda```と```cuda-8.0```があり，その両方に移動した．

```
$ sudo cp ./cudnn.h /usr/local/cuda/include
$ sudo cp ./cudnn.h /usr/local/cuda-8.0/include

$ sudo cp ./* /usr/local/cuda/lib64
$ sudo cp ./* /usr/local/cuda-8.0/lib64
```

どちらか片方だけだと```ImportError: libcudnn.so.5: cannot open shared object file: No such file or directory
```というエラーを吐いた．


# 6.2.ドライバーがないエラー
```text
In [1]: %timeit -n 1 -r 1 %run mnist_cnn.py
Using TensorFlow backend.
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
2017-06-26 14:03:56.377779: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-06-26 14:03:56.377825: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-06-26 14:03:56.418415: E tensorflow/stream_executor/cuda/cuda_driver.cc:406] failed call to cuInit: CUDA_ERROR_UNKNOWN
2017-06-26 14:03:56.418677: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:145] kernel driver does not appear to be running on this host (cosmos): /proc/driver/nvidia/version does not exist
 3584/60000 [>.............................] - ETA: 127s - loss: 1.4717 - acc: 0.5474

```

というように，ドライバーがなくてGPUを検出できていないというような表示が出た．

## 6.3.ドライバーをダウンロードする

http://www.nvidia.co.jp/Download/index.aspx?lang=jp

![Screen Shot 2017-06-26 at 14.44.35.png](https://qiita-image-store.s3.amazonaws.com/0/164264/4191c9ea-292e-33b1-258b-b61ee61c7fe6.png "Screen Shot 2017-06-26 at 14.44.35.png")


ドライバーを入れようとしたが，以下のようなNouveau kernel driverに関するエラーが出た．

![Screen Shot 2017-06-26 at 16.00.55.png](https://qiita-image-store.s3.amazonaws.com/0/164264/417ded14-7ca2-6a52-ccbc-cbb8ba23da91.png "Screen Shot 2017-06-26 at 16.00.55.png")


https://www.softek.co.jp/SPG/Pgi/TIPS/public/accel/cuda40_install.html

この記事の，
> Nouveau kernel driverが存在するために、CUDAドライバーがインストールできない場合の対処

を参考に，black listにNouveauを追加してrebootした．これによって，正常にドライバーをインストールできた．

# 7.完成
動いた！

```ipyhton
In [1]: %timeit -n 1 -r 1 %run mnist_cnn.py
Using TensorFlow backend.
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
2017-06-26 16:53:56.009383: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-06-26 16:53:56.009431: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-06-26 16:53:56.848793: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:893] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2017-06-26 16:53:56.849080: I tensorflow/core/common_runtime/gpu/gpu_device.cc:940] Found device 0 with properties: 
name: GeForce GT 710
major: 3 minor: 5 memoryClockRate (GHz) 0.954
pciBusID 0000:01:00.0
Total memory: 980.75MiB
Free memory: 970.88MiB
2017-06-26 16:53:56.849126: I tensorflow/core/common_runtime/gpu/gpu_device.cc:961] DMA: 0 
2017-06-26 16:53:56.849143: I tensorflow/core/common_runtime/gpu/gpu_device.cc:971] 0:   Y 
2017-06-26 16:53:56.849180: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GT 710, pci bus id: 0000:01:00.0)
60000/60000 [==============================] - 114s - loss: 0.3256 - acc: 0.9009 - val_loss: 0.0758 - val_acc: 0.9759
Epoch 2/12
60000/60000 [==============================] - 110s - loss: 0.1120 - acc: 0.9670 - val_loss: 0.0527 - val_acc: 0.9831
Epoch 3/12
60000/60000 [==============================] - 110s - loss: 0.0855 - acc: 0.9745 - val_loss: 0.0443 - val_acc: 0.9858
Epoch 4/12
60000/60000 [==============================] - 110s - loss: 0.0719 - acc: 0.9789 - val_loss: 0.0370 - val_acc: 0.9865
Epoch 5/12
60000/60000 [==============================] - 110s - loss: 0.0621 - acc: 0.9817 - val_loss: 0.0362 - val_acc: 0.9879
Epoch 6/12
60000/60000 [==============================] - 110s - loss: 0.0570 - acc: 0.9835 - val_loss: 0.0326 - val_acc: 0.9885
Epoch 7/12
60000/60000 [==============================] - 110s - loss: 0.0499 - acc: 0.9853 - val_loss: 0.0344 - val_acc: 0.9894
Epoch 8/12
60000/60000 [==============================] - 110s - loss: 0.0485 - acc: 0.9855 - val_loss: 0.0298 - val_acc: 0.9911
Epoch 9/12
60000/60000 [==============================] - 110s - loss: 0.0441 - acc: 0.9874 - val_loss: 0.0304 - val_acc: 0.9899
Epoch 10/12
60000/60000 [==============================] - 109s - loss: 0.0416 - acc: 0.9878 - val_loss: 0.0289 - val_acc: 0.9910
Epoch 11/12
60000/60000 [==============================] - 110s - loss: 0.0398 - acc: 0.9882 - val_loss: 0.0295 - val_acc: 0.9899
Epoch 12/12
60000/60000 [==============================] - 109s - loss: 0.0374 - acc: 0.9888 - val_loss: 0.0274 - val_acc: 0.9909
Test loss: 0.0273571792022
Test accuracy: 0.9909
1 loop, best of 1: 22min 31s per loop
```

ちなみにcore i7のmultiprocessで28分で，GPUを使って22分なので，そんなに変わらない笑（Geforce 710なので仕方がない）

## 8.追加：その他のエラー
2017/12/11に新しいGPUを購入して設定したのでその時のメモ．
GTX1060を買った．ちなみに環境がcentosからubuntuに変わってる．

### 8.1ドライバーのバージョンの食い違い

```python
17-12-11 20:23:00.970215: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:189] libcuda reported version is: 384.90.0
2017-12-11 20:23:00.970253: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:369] driver version file contents: """NVRM version: NVIDIA UNIX x86_64 Kernel Module  384.98  Thu Oct 26 15:16:01 PDT 2017
GCC version:  gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5)
"""
2017-12-11 20:23:00.970277: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:193] kernel reported version is: 384.98.0
2017-12-11 20:23:00.970288: E tensorflow/stream_executor/cuda/cuda_diagnostics.cc:303] kernel version 384.98.0 does not match DSO version 384.90.0 -- cannot find working devices in this configuration
```
一度ドライバーを消し，6.3と同様のやり方で，`384.98.0`のドライバーを入れると消えた．
`384.98.0`のドライバーは英語サイトではなかなか見つからず，[日本サイト](http://www.nvidia.co.jp/object/unix-jp.html)ではすぐに見つかったのが謎だ．

## 9.参考情報
~~2017/12/11現在~~
~~[tensorflowのリリース](https://github.com/tensorflow/tensorflow/releases)を見ると，1.5.0からcuda9.0に対応する予定らしい．現在(1.4.0)は対応していない．~~
リリースされて対応した．

## 10.参考リンク
[UbuntuにNvidia GPUのDriver + CUDAをInstallする(GTX1080対応版)](https://qiita.com/conta_/items/d639ef0068c9b7a0cd12)