nvidia-docker2 で、PyTorch1.1 GPU環境を構築

# 目的
以前作っていた nvida-docker2 環境構築スクリプトを、改めて整理およびPyTorch1.1.0 に対応する。また、日本時刻にも対応する。

# 注意
GPU環境を使わない場合は、もっと簡易にPython 環境が構築できるので、あしからず。

# 環境
- OS：Ubuntu 18.04.2 LTS (Bionic Beaver)
- Memory: 64GiB
- CPU：Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz 4cores
- GPU：GeForce GTX 1080 Ti x 2
- CUDA：Cuda compilation tools, release 10.1, V10.1.105
    - CUDA は、インストール済として進めます。
    - [github](https://github.com/tkosht/template.git) のtemplate/pypj/scripts/docker/install_cuda10.sh, install_cudnn.sh は、インストールの参考スクリプトです。
- Python 3.6.8
    -  docker コンテナに、インストールするPython のバージョン

# コード
- [github](https://github.com/tkosht/template.git)
    - [template/pypj](https://github.com/tkosht/template/tree/master/pypj)

# 概説

## 準備
上記コードの[github](https://github.com/tkosht/template.git) をclone する。

```bash
git clone https://github.com/tkosht/template.git
cd template
```

## nvidia-docker2, docker-compose をインストール
```bash
cd $(git rev-parse --show-toplevel)/pypj/scripts/docker
sh install_docker.sh
```

## nvidia-docker-compose をインストール
```bash
cd $(git rev-parse --show-toplevel)/pypj/scripts/docker
pip install nvidia-docker-compose
```


## ビルド
docker-compose を使ってビルドする。

### シンプルにPython環境をビルドする場合
```bash
cd $(git rev-parse --show-toplevel)/pypj/docker
docker-compose build simple
```
※ 同ディレクトリで、`sh build.sh simple` と実行してもよい。


### pyenv環境をビルドする場合
```bash
cd $(git rev-parse --show-toplevel)/pypj/docker
docker-compose build pyenv
```
※ 同ディレクトリで、`sh build.sh pyenv` と実行してもよい。


### 両方ビルドする場合
```bash
cd $(git rev-parse --show-toplevel)/pypj/docker
docker-compose build
```
※ 同ディレクトリで、`sh build.sh` と実行してもよい。

## GPU環境の確認

### Python環境
nvidia-smi コマンドを実行して、エラーが起きないことを確認する。

```bash
docker run --runtime=nvidia -it --rm gpuenv:simple nvidia-smi

Mon Jun 24 01:46:19 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.56       Driver Version: 418.56       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 GTX 108...  Off  | 00000000:01:00.0  On |                  N/A |
| 26%   42C    P8     9W / 250W |    602MiB / 11176MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 108...  Off  | 00000000:02:00.0 Off |                  N/A |
| 23%   33C    P8     8W / 250W |      2MiB / 11178MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

```

### pyenv環境
上記と同じように確認する。

```bash
docker run --runtime=nvidia -it --rm gpuenv:pyenv nvidia-smi
```

## 動作確認
PyTorch の example/vae を使って動作確認をする。
別のターミナルで、`nvidia-smi -l 1` を実行すると良い。

```bash
d=$(git rev-parse --show-toplevel)/pypj
hostdir="$d/data"                   # host                                                                                                  
labdir="/home/gpuser/pj/lab"        # container
datadir="$labdir/examples/data"     # container
workdir="$labdir/examples/vae"      # container
mkdir -p $hostdir
opts="-v $hostdir:$datadir -w $workdir -it --rm"
docker run --runtime=nvidia $opts gpuenv:simple python main.py

Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to ../data/MNIST/raw/train-images-idx3-ubyte.gz
9920512it [00:09, 1076915.85it/s]                       
Extracting ../data/MNIST/raw/train-images-idx3-ubyte.gz 
: --- 8< --- (snip) --- 8< --- 8< --- 8< --- 8< --- 8< ---
Train Epoch: 10 [56320/60000 (94%)]     Loss: 107.074844
Train Epoch: 10 [57600/60000 (96%)]     Loss: 108.066971
Train Epoch: 10 [58880/60000 (98%)]     Loss: 103.747894
====> Epoch: 10 Average loss: 106.3138
====> Test set loss: 105.6189
```
※ 標準出力をバッファリングさせないように、`-it` を指定している。

```bash
d=$(git rev-parse --show-toplevel)/pypj
hostdir="$d/data"                   # host                                                                                                  
labdir="/home/gpuser/pj/lab"        # container
datadir="$labdir/examples/data"     # container
workdir="$labdir/examples/vae"      # container
mkdir -p $hostdir
opts="-v $hostdir:$datadir -w $workdir -it --rm"
docker run --runtime=nvidia $opts gpuenv:pyenv python main.py
```

## 参考
- [Docker Ubuntu18.04でtzdataをinstallするときにtimezoneの選択をしないでinstallする](https://qiita.com/yagince/items/deba267f789604643bab)
- [nvidia-docker でポータブルな機械学習の作業環境を作る](https://qiita.com/legokichi/items/7bf3862569cfca122d73)