GPU付きのTensorflowをUbuntu18.04に入れる

# この記事で紹介すること
この記事では、Ubuntu 18.04にGPU付きのTensorflowを入れる方法を紹介します。というかほとんど下の記事が素晴らしかったので、それを紹介する記事です。

[Install TensorFlow with GPU Support the Easy Way on Ubuntu 18.04 (without installing CUDA)](https://www.pugetsystems.com/labs/hpc/Install-TensorFlow-with-GPU-Support-the-Easy-Way-on-Ubuntu-18-04-without-installing-CUDA-1170/)

# 作業環境
* Ubuntu 18.04
* NVIDIA RTX2080
* Python 3.6.8 (Anaconda)

# この環境にTensorflow-gpuを入れる難しさ
上の環境を見るとわかりますが、私はGPUとしてRTXシリーズを使っており、CUDAのバージョンが10系に属します(私の場合には10.1)。これはネットを調べてみると、Tensorflow-gpuは正式には対応していないという感じになっているようです。

先月には下のような記事が書かれており、preview版でようやく対応し始めたといった感じに見えます。

[【CUDA10化でGPUもOK!】TensorFlow 2.0 Previewを最速で試す on Colaboratory](https://qiita.com/tomo_makes/items/9c22f306f1b781e8a7c2)

私も色々試してみて、CUDAのバージョンがdriverと合わないと言われてdriverをダウングレードしたらパソコンが起動しなくなってOS入れ直す、、、ということにもなりました（泣）。ここでは私が色々やって最終的にうまく行った方法を紹介します。

# NVIDIA-Driverを入れる
NVIDIA-Driverは調べるとaptで入れる方法など結構色々出てきますが、私はrunfileをダウンロードしてそこからやりました。まず、[NVIDIAの公式サイト](https://www.nvidia.co.jp/Download/index.aspx?lang=jp)から、自分のGPUとOSにあったドライバをインストールします。

つぎに、これを実行するために必要なソフトをインストールします。ターミナルから

```bash
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install build-essential
```

を実行します。upgradeでエラーが出て```--fix-missing```をつけてみろとか出る場合には、

```bash
$ sudo apt --fix-missing upgrade
```
とします。ここからドライバを入れてきますが、このためには一度GUIを消さなければいけません。

```bash
$ sudo service lightdm stop
```

私の場合、Ubuntuをインストールしたてで画面の解像度も自由に変えられないような状況（多分グラフィック系のドライバが機能していない状況？）でやったせいか、このコマンドはエラーが出ていましたが、最終的には問題はありませんでした。ここからの操作はCUIで行います。Ctrl+Alt+F4(よくあるサイトではF1となっているが、私の場合には効かなかった)を押すと、黒い画面になるので、ユーザー名とパスワードを入力してログインします。

あとは、先程ダウンロードしたrunfileのあるフォルダまで```cd```使って移動して、

```bash
$ sudo ./NVIDIA-Linux-x86_64-418.43.run    #数字はダウンロードした時期によって異なる
```

を実行します。途中でエラー出たけどどうする？みたいな画面が出て、インストールを続けるかやめるか選択する画面が何個か出てきたのですが全部無視してインストールを続けたら最終的には問題ありませんでした。

```bash
$ sudo reboot
```
で再起動して、ターミナルから

```bash
$ nvidia-smi
```
と入力して

```bash
Thu Mar 14 22:20:48 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.43       Driver Version: 418.43       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| 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 RTX 2080    Off  | 00000000:01:00.0  On |                  N/A |
|  0%   43C    P8    20W / 215W |    591MiB /  7949MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1158      G   /usr/lib/xorg/Xorg                            18MiB |
|    0      1209      G   /usr/bin/gnome-shell                          57MiB |
|    0      1896      G   /usr/lib/xorg/Xorg                           132MiB |
|    0      2008      G   /usr/bin/gnome-shell                         117MiB |
|    0      2434      G   /proc/self/exe                                67MiB |
|    0      8617      C   /home/yudai/.conda/envs/tf-gpu/bin/python    193MiB |
+-----------------------------------------------------------------------------+

```

のような画面が表示されれば成功です。

# Anacondaを入れる
次に、Pythonの環境を構築します。CUDAやCUDNNのインストールは？という声が聞こえてきそうですが、実はcondaでできます。

[Anacondaの公式サイト](https://www.anaconda.com/distribution/)からLinux用のPython3系のシェルスクリプトを落とします。ダウンロードしたディレクトリに移動して

```bash
$ chmod +x Anaconda3-2018.12-Linux-x86_64.sh
$ sudo ./Anaconda3-2018.12-Linux-x86_64.sh
```
利用規約みたいなものに従うかみたいなことを聞いてきますがyesとして進んでいけばインストールできます。最後の方にAnacondaにpathを通すかみたいなことを聞いてきて、デフォルトでnoとなっていますが、ここでnoとした人は自力でpathを通しておきます。

ターミナルを一度消してつけると、condaコマンドが使えるようになっています。

```bash
$ conda -V
conda 4.5.12
```
Tensorflow用の仮想環境を作ります。

```bash
$ conda create -n tf-gpu 
$ conda activate tf-gpu    # 仮想環境を起動
```

# Tensorflowを入れる
condaでTensorflowを入れます。

```bash
(tf-gpu)$ conda install tensorflow-gpu
```

すると、下のような表示が出てきます。

```bash
The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    tensorflow-base-1.12.0     |gpu_py36had579c0_0       216.9 MB
    tensorboard-1.12.2         |   py36he6710b0_0         3.1 MB
    libedit-3.1.20181209       |       hc058e9b_0         188 KB
    wheel-0.33.1               |           py36_0          39 KB
    six-1.12.0                 |           py36_0          22 KB
    cudatoolkit-9.2            |                0       351.0 MB
    tensorflow-1.12.0          |gpu_py36he74679b_0           3 KB
    grpcio-1.16.1              |   py36hf8bcb03_1         1.1 MB
    markdown-3.0.1             |           py36_0         107 KB
    h5py-2.9.0                 |   py36h7918eee_0         1.2 MB
    cudnn-7.3.1                |        cuda9.2_0       334.6 MB
    _tflow_select-2.1.0        |              gpu           2 KB
    pip-19.0.3                 |           py36_0         1.9 MB
    setuptools-40.8.0          |           py36_0         647 KB
    numpy-1.16.2               |   py36h7e9f1db_0          49 KB
    termcolor-1.1.0            |           py36_1           7 KB
    numpy-base-1.16.2          |   py36hde5b4d6_0         4.4 MB
    protobuf-3.6.1             |   py36he6710b0_0         616 KB
    mkl_random-1.0.2           |   py36hd81dba3_0         407 KB
    gast-0.2.2                 |           py36_0         138 KB
    keras-preprocessing-1.0.9  |             py_0          35 KB
    mkl_fft-1.0.10             |   py36ha843d7b_0         170 KB
    libprotobuf-3.6.1          |       hd408876_0         4.1 MB
    ca-certificates-2019.1.23  |                0         126 KB
    astor-0.7.1                |           py36_0          43 KB
    openssl-1.1.1b             |       h7b6447c_1         4.0 MB
    sqlite-3.27.2              |       h7b6447c_0         1.9 MB
    hdf5-1.10.4                |       hb1b8bf9_0         5.3 MB
    tensorflow-gpu-1.12.0      |       h0d30ee6_0           2 KB
    keras-applications-1.0.7   |             py_0          33 KB
    certifi-2019.3.9           |           py36_0         155 KB
    scipy-1.2.1                |   py36h7c811a0_0        17.7 MB
    c-ares-1.15.0              |       h7b6447c_1          98 KB
    absl-py-0.7.0              |           py36_0         156 KB
    werkzeug-0.14.1            |           py36_0         423 KB
    cupti-9.2.148              |                0         1.7 MB
    python-3.6.8               |       h0371630_0        34.4 MB
    ------------------------------------------------------------
                                           Total:       986.7 MB

The following NEW packages will be INSTALLED:

    _tflow_select:       2.1.0-gpu                
    absl-py:             0.7.0-py36_0             
    astor:               0.7.1-py36_0             
    blas:                1.0-mkl                  
    c-ares:              1.15.0-h7b6447c_1        
    ca-certificates:     2019.1.23-0              
    certifi:             2019.3.9-py36_0          
    cudatoolkit:         9.2-0                    
    cudnn:               7.3.1-cuda9.2_0          
    cupti:               9.2.148-0                
    gast:                0.2.2-py36_0             
    grpcio:              1.16.1-py36hf8bcb03_1    
    h5py:                2.9.0-py36h7918eee_0     
    hdf5:                1.10.4-hb1b8bf9_0        
    intel-openmp:        2019.1-144               
    keras-applications:  1.0.7-py_0               
    keras-preprocessing: 1.0.9-py_0               
    libedit:             3.1.20181209-hc058e9b_0  
    libffi:              3.2.1-hd88cf55_4         
    libgcc-ng:           8.2.0-hdf63c60_1         
    libgfortran-ng:      7.3.0-hdf63c60_0         
    libprotobuf:         3.6.1-hd408876_0         
    libstdcxx-ng:        8.2.0-hdf63c60_1         
    markdown:            3.0.1-py36_0             
    mkl:                 2019.1-144               
    mkl_fft:             1.0.10-py36ha843d7b_0    
    mkl_random:          1.0.2-py36hd81dba3_0     
    ncurses:             6.1-he6710b0_1           
    numpy:               1.16.2-py36h7e9f1db_0    
    numpy-base:          1.16.2-py36hde5b4d6_0    
    openssl:             1.1.1b-h7b6447c_1        
    pip:                 19.0.3-py36_0            
    protobuf:            3.6.1-py36he6710b0_0     
    python:              3.6.8-h0371630_0         
    readline:            7.0-h7b6447c_5           
    scipy:               1.2.1-py36h7c811a0_0     
    setuptools:          40.8.0-py36_0            
    six:                 1.12.0-py36_0            
    sqlite:              3.27.2-h7b6447c_0        
    tensorboard:         1.12.2-py36he6710b0_0    
    tensorflow:          1.12.0-gpu_py36he74679b_0
    tensorflow-base:     1.12.0-gpu_py36had579c0_0
    tensorflow-gpu:      1.12.0-h0d30ee6_0        
    termcolor:           1.1.0-py36_1             
    tk:                  8.6.8-hbc83047_0         
    werkzeug:            0.14.1-py36_0            
    wheel:               0.33.1-py36_0            
    xz:                  5.2.4-h14c3975_4         
    zlib:                1.2.11-h7b6447c_3        

Proceed ([y]/n)?
```
これらも一緒にインストールされますということですが、この中にちゃんとCUDAとCUDNNが含まれていることがわかります。（表の中にはPython3.6.8も含まれており、Python3.7から、勝手にTensorflowが使える3.6へ変えてくれるみたいです。私みたいに仮想環境を作るときに```python=3.6```の指定を忘れても安心です。）もちろんyを入力して、Enterを押すとインストールが完了します。

## インストールが成功したか確認する
インタラクティブセッションからTensorflowのインストールが成功したか確認してみます。

```bash
(tf-gpu)$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow    # うまく行っていれば何も出ない
>>> from tensorflow.python.client import device_lib
>>> device_lib.list_local_devices()

2019-03-14 20:57:26.256058: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2019-03-14 20:57:26.380768: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:964] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-03-14 20:57:26.381151: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties: 
name: GeForce RTX 2080 major: 7 minor: 5 memoryClockRate(GHz): 1.71
pciBusID: 0000:01:00.0
totalMemory: 7.76GiB freeMemory: 7.27GiB
2019-03-14 20:57:26.381162: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0
2019-03-14 20:57:26.581479: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-03-14 20:57:26.581521: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988]      0 
2019-03-14 20:57:26.581525: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0:   N 
2019-03-14 20:57:26.581758: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:0 with 6996 MB memory) -> physical GPU (device: 0, name: GeForce RTX 2080, pci bus id: 0000:01:00.0, compute capability: 7.5)
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 11506288966317652745
, name: "/device:XLA_CPU:0"
device_type: "XLA_CPU"
memory_limit: 17179869184
locality {
}
incarnation: 6411188702482698463
physical_device_desc: "device: XLA_CPU device"
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 11648397151798772763
physical_device_desc: "device: XLA_GPU device"
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 7336188314
locality {
  bus_id: 1
  links {
  }
}
incarnation: 17893800951759650774
physical_device_desc: "device: 0, name: GeForce RTX 2080, pci bus id: 0000:01:00.0, compute capability: 7.5"
]

```

ちゃんとRTX2080が認識されていることがわかります。

## Jupyter Notebookで使えるようにする。
Jupyter Notebookでこれを使えるようにするには、

```bash
(tf-gpu)$ conda install ipykernel
(tf-gpu)$ python -m ipykernel install --user --name tf-gpu --display-name "TensorFlow-GPU"
```
などとすれば、Jupyter Notebookを開いてNewをクリックしたときに"TensorFlow-GPU"という選択肢が現れます。

# 補足　（2019/05/04追加）
現在、上のコマンド

```python
conda install tf-gpu
```
を使うとデフォルトでtensorflow-gpu==1.13.1が入るようになっていますが、これを使ってみたところCuDNNの部分でエラーが発生しました。原因はこれ以上今のところはわかりませんが、もしも上の方法でエラーが出るようなら1.12.0バージョンを指定してやってみてください。

```python
conda install tensorflow-gpu==1.12.0
```