TensorFlow1.10.1をUbuntu18.04 + CUDA9.2 + cuDNN 7.2.1上で動かす


本記事は2018-05-31に公開された[こちらの記事](http://www.python36.com/how-to-install-tensorflow-gpu-with-cuda-9-2-for-python-on-ubuntu/
)を参考にしたものです。
バージョンを2018-09-19時点で利用可能な最新ものにして解説しています。
CUDA関係は依存関係が面倒なので順序通りに実行することをおすすめします。

##最新のバージョンにした理由
CUDA、 cuDNN、 TensorFlowなどは動く限り最新のバージョンにしたほうが
学習時間が短くなるようです。[こちら](http://www.python36.com/benchmark-tensorflow-on-cifar10/)にベンチマークが出ています。
CUDA8.0、 cuDNN6.0、 TensorFlow1.4.1と比較すると実行時間が約37%短縮されています。


##GPUと想定する環境

使用するGPUは 

- GeForce GTX 1080 Ti

です。
ネイティブ環境でpython 3.6.5を使用し、
TensorFlowでKerasなどを利用することを想定しています。


##Step 1: システムの状態を最新にする
```bash
$ sudo apt update 
$ sudo apt upgrade
```
##Step 2: CUDAが使用可能なGPUか確認する
####GPUの型番を調べる
自分のGPUでCUDAが使えることがわかっていてもこの部分を飛ばさないようにしてください。
以下を端末で実行します。

```
$ lspci | grep -i nvidia
```
すると、

>0000:a6:00.0 VGA compatible controller:
<font color="Red">NVIDIA</font> Corporation GP102 \[GeForce GTX 1080 Ti\] (rev a1)
0000:a6:00.1 Audio device:
<font color="Red">NVIDIA</font> Corporation GP102 HDMI Audio Controller (rev a1)

と表示されました。 

\[GeForce GTX 1080 Ti\] という部分があります。
これが搭載されているGPUです。

※ここでGPU名が出てこないこともあります。(メーカー製ノートに多い)
　その場合は無視していったん進みましょう。
　Step 8の途中でコマンド`$ nvidia-smi`を実行すると出てくる表示の中に型番があります。
　そして戻ってきてCompute Capabilityを調べます。
####Compute Capabilityを調べる
http://developer.nvidia.com/cuda-gpus にアクセスします。
リンク先のページで自分の型番のGPUが含まれているのを確認します。
そこに書かれているCompute Capabilityを確認して**メモしておいてください**。

自分のGeForce GTX 1080 Tiは6.1でした。

|GPU|Compute Capability|
|:---|:---|
|GeForce GTX 1080 Ti|6.1|


（この数字はこれから変更になるとも限らないので注意が必要です）

##Step 3: Ubuntuのバージョンの確認
以下のコマンドを端末で実行します。

```
$ uname -m && cat /etc/*release
```
すると、

>x86_64
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

などと表示されるはずです。


##Step 4: 必要なパッケージをインストール
必要なパッケージをインストールします。

```
$ sudo apt install build-essential 
$ sudo apt install cmake git unzip zip
$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt update
$ sudo apt install python2.7-dev python3.5-dev python3.6-dev pylint
```
**python 3.6系を使う人でも最後のコマンドの**
`python2.7-dev` `python3.5-dev`  `pylint`**が必要です。**
**TensorFlowをコンパイルするのに必要だからです。**

##Step 5: Linuxカーネルヘッダーのインストール
端末で以下のコマンドを実行します。

```
$ uname -r
```
Linuxカーネルのバージョンが返ってきます。


>4.15.0-33-generic

Linuxカーネルのバージョンが返ってくることを確認したら、
Linuxカーネルヘッダーをインストールします。
以下のコマンドを端末で実行してください。

```
$ sudo apt install linux-headers-$(uname -r)
```
##Step 6: CUDA 9.2のインストール
####プリインストールされているNVIDIAグラフィックドライバとCUDAのアンインストール
CUDAは他のUbuntuのパッケージのように以前のバージョンから自動でアップグレードできません。
マイナーバージョンの違いも自動でアップグレードされません。
このマイナーバージョンの違いがグラフィックなどのトラブルを引き起こします。

そのため一度NVIDIAのグラフィックドライバとCUDA関係を全てアンインストールします。

設定ファイルも消去します。

- CUDAインストールの際正しいバージョンのNVIDIAグラフィックドライバが入ります。
- この方法以外のインストールでは正しいバージョンのNVIDIAのグラフィックドライバが入らないことがあります。

```
$ sudo apt purge nvidia*
$ sudo apt autoremove
$ sudo apt autoclean
$ sudo rm -rf /usr/local/cuda*
```


####CUDAのインストール
```
$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1710/x86_64/7fa2af80.pub
$ echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1710/x86_64 /" | sudo tee /etc/apt/sources.list.d/cuda.list
$ sudo apt update 
$ sudo apt -o Dpkg::Options::="--force-overwrite" install cuda-9-2 cuda-drivers
```
１つめのコマンドではキーに追加するファイルのURLに/ubuntu1710/が含まれています。
実は本来Ubuntu17.10にインストールする用なのですがUbuntu18.04でも問題なく動きます。
強制的にインストールするために最後のコマンドでは`"--force-overwrite"`のオプションを付加しています。

Ubuntu18.04版は正式リリースされていないので、この部分を/ubuntu1804/に変えても
「データがありません」と返ってきてしまいます。
(正式にUbuntu18.04版がリリースされたらそちらのURLに変えて実行しても良いかもしれません)

##Step 7: 再起動
NVIDIAドライバを読み込むために、一度Ubuntuを再起動します。

```
$ reboot
```

##Step 8: パスの追加
先程インストールしたCUDA 9.2に対して`.bashrc`にパスを追加します。
端末を開き以下のコマンドを実行します。

```
$ echo 'export PATH=/usr/local/cuda-9.2/bin${PATH:+:${PATH}}' >> ~/.bashrc
$ echo 'export LD_LIBRARY_PATH=/usr/local/cuda-9.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}' >> ~/.bashrc
```
設定を再読込して適用します。

```
$ source ~/.bashrc
$ sudo ldconfig
```
これでCUDA 9.2が実行できるようになりました。
以下のコマンドでNVIDIAドライバのバージョンとCUDAのバージョンを確認できます。

```
$ nvidia-smi
$ nvcc -V
```
それぞれこのように返ってきます。

>Driver Version: 396.44
（本当はもう少し詳細に出てきます）

<div></div>
>nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Tue_Jun_12_23:07:04_CDT_2018
Cuda compilation tools, release 9.2, V9.2.148


NVIDIAグラフィックドライバのバージョンが396.44、
CUDAのバージョンが9.2.148だとわかります。

##Step 9: cuDNN 7.2.1のインストール
Deep Neural Networksを動かす際にGPUのパフォーマンスを向上させるためのライブラリーです。

https://developer.nvidia.com/cudnn へ行きダウンロードします。

ダウンロードするためにはにはアカウントの登録(無料)が必要です。登録自体はすぐに終わります。

アカウント登録後、ログインして上記のリンクのところへもう一度行きます。

サイトにある`Download cuDNN`を選択します。
するとソフトウェアライセンスへの同意を求められるので、
 I Agree To the Terms of the cuDNN Software License Agreement にチェックします。

`Download cuDNN v7.2.1 (August 7, 2018), for CUDA 9.2`
\> `cuDNN v7.2.1 Library for Linux` の順に選択し、ファイルを保存します。

ダウンロードしたフォルダに移動します

```
$ cd <ダウンロードしたフォルダ>
```
そして以下のコマンドを順に実行します。
１つめのコマンドでいまダウンロードしたcuDNNの.tgzファイルを展開しています。
**ここは自分のダウンロードしたファイルの名前にしてください。**（ls などで確認すると良いでしょう）

```
$ tar -xf cudnn-9.2-linux-x64-v7.2.1.38.tgz
$ sudo cp -R cuda/include/* /usr/local/cuda-9.2/include
$ sudo cp -R cuda/lib64/* /usr/local/cuda-9.2/lib64
```




##Step 10: NCCL 2.2.13のインストール
https://developer.nvidia.com/nccl へアクセスし`Download NCLL`を選択します。

使用目的や使用方法のアンケートに答えるとダウンロードできるようになります。
**アンケートで答えた内容はダウンロード内容には影響しない**ので適当で大丈夫です。

ソフトウェアライセンスへの同意を求められるので、
I Agree To the Terms of the Software License Agreement にチェックします。

インストールしたCUDAのバージョンは9.2になので、
`Download NCCL v2.2.13, for CUDA 9.2, June 1, 2018` 
\> `NCCL 2.2.13 O/S agnostic and CUDA 9.2` の順に選択しファイルを保存します。

ダウンロードしたフォルダに移動します。

```
$ cd <ダウンロードしたフォルダ>
```
そして以下のコマンドを実行します。

１つめのコマンドはダウンロードしたncclの.tgzファイルを展開しています。
2つめのコマンドは展開したフォルダに移動しています。
**それぞれ自分のダウンロードしたファイルの名前、展開したフォルダの名前にしてください。**

```
$ tar -xf nccl_2.2.13-1+cuda9.2_x86_64.txz
$ cd nccl_2.2.13-1+cuda9.2_x86_64
$ sudo cp -R * /usr/local/cuda-9.2/targets/x86_64-linux/
$ sudo ldconfig
```



##Step 11: 必要なパッケージのインストール
####libcupti
```
$ sudo apt install libcupti-dev
$ echo 'export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
```
####pythonのパッケージ
```
$ sudo apt install python3-numpy python3-dev python3-pip python3-wheel
```
今回 python 3.6.5を使用するためこのようにしています。





##step12: TensorFlowをビルドするための準備


####bazelのダウンロードとインストール

```
$ cd ~/
$ wget https://github.com/bazelbuild/bazel/releases/download/0.16.1/bazel-0.16.1-installer-linux-x86_64.sh
$ chmod +x bazel-0.16.1-installer-linux-x86_64.sh
$ ./bazel-0.16.1-installer-linux-x86_64.sh --user
$ echo 'export PATH="$PATH:$HOME/bin"' >> ~/.bashrc
```
bazelはTensorFlowをソースからビルドする際に必要なコンパイラです。
現時点で最新の0.16.1をgithubからダウンロードしてインストールします。

TensorFlow 1.10.1はバージョン0.16.1のbazelでコンパイルできました。

* これから先TensorFlowのバージョンは更新されるでしょう。
その場合0.16.1のbazelではコンパイルできないかもしれません。

* この場合には、
https://github.com/bazelbuild/bazel/releases から
`bazel-<バージョン名>-installer-linux-x86_64.sh`を見つけて右クリックし
`リンクをコピー`。そしてコピーしたurlで2つめのコマンドのurlを置き換えてください。


####環境変数の再読込
```
$ source ~/.bashrc
$ sudo ldconfig
```


####TensorFlowのソースをダウンロード
TensorFlowをダウンロードして最新の1.10にブランチを切り替えます。

```
$ cd ~/
$ git clone https://github.com/tensorflow/tensorflow.git
$ cd tensorflow
$ git pull
$ git checkout r1.10
```


####TensorFlowのインストール設定
```
$ ./configure
```
このコマンドを実行すると設定に入ります。
端末上で詳細に設定していきます。
間違えた場合は`Ctrl + c`で中断し、もう一度`$ ./configure`からやり直しましょう。

>WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
You have bazel 0.16.1 installed.
Please specify the location of python. [Default is /usr/bin/python]: 

とpythonのパスを聞かれます。

`/usr/bin/python3`と入力し`ENTERキー`を押します。

すると
>Found possible Python library paths:
  /usr/lib/python3/dist-packages
  /usr/local/lib/python3.6/dist-packages
Please input the desired Python library path to use.  Default is [/usr/lib/python3/dist-packages]

と出てくるので`/usr/lib/python3/dist-packages`と入力して`ENTERキー`

次に以下のように設定していきます。（赤字部分が入力するところ）

>
Do you wish to build TensorFlow with jemalloc as malloc support? [Y/n]: <font color="Red">y</font>
jemalloc as malloc support will be enabled for TensorFlow.
Do you wish to build TensorFlow with Google Cloud Platform support? [Y/n]: <font color="Red">y</font>
Google Cloud Platform support will be enabled for TensorFlow.
Do you wish to build TensorFlow with Hadoop File System support? [Y/n]: <font color="Red">y</font>
Hadoop File System support will be enabled for TensorFlow.
Do you wish to build TensorFlow with Amazon AWS Platform support? [Y/n]: <font color="Red">y</font>
Amazon AWS Platform support will be enabled for TensorFlow.
Do you wish to build TensorFlow with Apache Kafka Platform support? [Y/n]: <font color="Red">y</font>
Apache Kafka Platform support will be enabled for TensorFlow.
Do you wish to build TensorFlow with XLA JIT support? [y/N]: <font color="Red">n</font>
No XLA JIT support will be enabled for TensorFlow.
Do you wish to build TensorFlow with GDR support? [y/N]: <font color="Red">n</font>
No GDR support will be enabled for TensorFlow.
Do you wish to build TensorFlow with VERBS support? [y/N]: <font color="Red">n</font>
No VERBS support will be enabled for TensorFlow.
Do you wish to build TensorFlow with OpenCL SYCL support? [y/N]: <font color="Red">n</font>
No OpenCL SYCL support will be enabled for TensorFlow.
Do you wish to build TensorFlow with CUDA support? [y/N]: <font color="Red">y</font>
CUDA support will be enabled for TensorFlow.
Please specify the CUDA SDK version you want to use. 
[Leave empty to default to CUDA 9.0]: <font color="Red">9.2</font>
Please specify the location where CUDA 9.2 toolkit is installed. 
Refer to README.md for more details. 
[Default is /usr/local/cuda]: <font color="Red">/usr/local/cuda-9.2</font>
Please specify the cuDNN version you want to use.
 [Leave empty to default to cuDNN 7.0]: <font color="Red">7.2.1</font>
Please specify the location where cuDNN 7 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda-9.2]:<font color="Red">/usr/local/cuda-9.2</font>
Do you wish to build TensorFlow with TensorRT support? [y/N]: <font color="Red">n</font>
No TensorRT support will be enabled for TensorFlow.
Please specify the NCCL version you want to use. If NCCL 2.2 is not installed, then you can use version 1.3 that can be fetched automatically but it may have worse performance with multiple GPUs. [Default is 2.2]: <font color="Red">2.2</font>
Please specify the location where NCCL 2 library is installed. 
Refer to README.md for more details.
 [Default is /usr/local/cuda-9.2]:<font color="Red">/usr/local/cuda-9.2/targets/x86_64-linux</font>

次にこのように表示されます。ここで**Step 2でメモしておいたCompute Capabilityを入力**します。
今回は**6.1**を入力します。
>Please specify a list of comma-separated Cuda compute capabilities you want to build with.
You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
Please note that each additional compute capability significantly increases your build time and binary size. [Default is: 6.1]<font color="red">6.1</font>

<div></div>

>Do you want to use clang as CUDA compiler? [y/N]: <font color="Red">n</font>
nvcc will be used as CUDA compiler.
Please specify which gcc should be used by nvcc as the host compiler. [Default is /usr/bin/gcc]: <font color="Red">/usr/bin/gcc</font>
Do you wish to build TensorFlow with MPI support? [y/N]: <font color="Red">n</font>
No MPI support will be enabled for TensorFlow.
Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native]: <font color="Red">-march=native</font>
Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: <font color="Red">n</font>
Not configuring the WORKSPACE for Android builds.

これで入力はおしまいです。
最後に以下のように表示されたら設定は完了です。
>Preconfigured Bazel build configs. You can use any of the below by adding "--config=<>" to your build command. See tools/bazel.rc for more details.
	--config=mkl         	# Build with MKL support.
	--config=monolithic  	# Config for mostly static monolithic build.
Configuration finished





##Step13: bazelでTensorFlowをビルドする

####TensorFlowのpipパッケージをビルドする
```
$ bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
```
ビルドに失敗してやり直す際はStep 12の`./configure`をもう一度

####whlファイルをビルドするために以下のコマンドを実行
```
$ bazel-bin/tensorflow/tools/pip_package/build_pip_package tensorflow_pkg
```
####pipでインストール
```
$ cd tensorflow_pkg
$ pip3 install tensorflow*.whl
```


##Step 14: 動作の確認
端末でpython3を起動します。

```
$ python3
```
バージョンを確認し簡単なプログラムを実行します。

```:python3
>>import tensorflow as tf
>>tf.__version__
'1.10.1'
>>hello = tf.constant('Hello, TensorFlow!')
>>sess = tf.Session()
>>sess.run(hello)
b'Hello, TensorFlow!'
```
このようになれば成功です。
お疲れ様でした。