TensorFlow with GPU on Docker を AWS で起動する

# 構成

https://github.com/NVIDIA/nvidia-docker にある以下の図が分かりやすい。

![図](https://cloud.githubusercontent.com/assets/3028125/12213714/5b208976-b632-11e5-8406-38d379ec46aa.png)

今回、Server は AWS の p2 インスタンス (GPU インスタンス)。
Host OS は Ubuntu 16.04 を利用する。

手動でインストールが必要なものは以下の通り。

- CUDA Toolkit / CUDA Driver
    - NVIDIA GPU をコントロールするために必要
    - 2つ同時にインストールされる
- Docker Engine
- nvidia-docker
    - Docker コンテナ内から CUDA Toolkit 経由で GPU を触るために必要

# 1. AWS インスタンス起動

GPU インスタンスの p2, p3 系を起動する。

<dl>
  <dt>AMI</dt>
  <dd>Ubuntu Server 16.04 LTS (HVM), SSD Volume Type</dd>
  <dt>備考</dt>
  <dd>ディスクサイズは 100 GB に変更する (デフォルトは 8 GB、足りない)</dd>
</dl>

# 2. CUDA のインストール

[公式ドキュメント](http://docs.nvidia.com/cuda/cuda-installation-guide-linux/) 通りに進める。
ただ、ドキュメントが長いので読まない方が良い。ハマると果てしなくハマって辛い。

実際に必要なのは3箇所のみ。

- "2. Pre-installation Actions" > "2.6. Download the NVIDIA CUDA Toolkit"
- "3. Package Manager Installation" > "3.6. Ubuntu"
- "7. Post-installation Actions" > "7.1.1. Environment Setup"

実際のコマンドは以下の通り。

```
## 2.6 Pre-installation Actions (Download the NVIDIA CUDA Toolkit)
$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb

## 3.6 Package Manager Installation (Ubuntu)
$ sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get install cuda

## 7.1.1 Post-installation Actions (Environment Setup)
$ echo 'export PATH=/usr/local/cuda-9.1/bin${PATH:+:${PATH}}' >> ~/.bashrc
$ source ~/.bashrc
```

nvcc が入れば成功。

```
$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Nov__3_21:07:56_CDT_2017
Cuda compilation tools, release 9.1, V9.1.85
```

# 3. Docker のインストール

[公式ドキュメント (Install using the repository)](https://docs.docker.com/engine/installation/linux/ubuntu/#install-using-the-repository) 通りに、Docker CE をインストールする。

インストール完了したら、sudo 無しで動作するよう ubuntu ユーザを docker グループに追加して、SSH ログインし直す。

```
$ sudo usermod -aG docker ubuntu
```

hello-world が動けば完了。

```
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...
```

# 4. nvidia-docker のインストール

[公式ドキュメント](https://github.com/NVIDIA/nvidia-docker) 通りに進める。

"Quick start" > "ubuntu distributions" のコマンドを実行すればOK。

以下のコマンドで Docker コンテナがホスト (p2 インスタンス) の GPU を認識していることが確認できる。

```
$ nvidia-docker run --rm nvidia/cuda nvidia-smi
Sun Apr 23 06:10:55 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.39                 Driver Version: 375.39                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 0000:00:1E.0     Off |                    0 |
| N/A   47C    P8    28W / 149W |      0MiB / 11439MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

# TensorFlow

あとは TensorFlow でもなんでもコンテナ内から GPU が触れる。

https://hub.docker.com/r/tensorflow/tensorflow/

```
$ nvidia-docker run -it -p 8888:8888 tensorflow/tensorflow:latest-gpu
```