GCP上にKaggleのDocker(GPU版)で計算環境を構築する

GCPで[KaggleのPython Docker(GPU版)](https://github.com/Kaggle/docker-python)を立ち上げてみた。
（参考記事：[GCPとDockerでKaggle用計算環境構築](https://qiita.com/lain21/items/a33a39d465cd08b662f1) ）

# GCPインスタンスの立ち上げ

GCPとDockerでKaggle用計算環境構築
https://qiita.com/lain21/items/a33a39d465cd08b662f1
を参考にインスタンスを立ち上げ

# gcloudの設定
GCP上のインスタンスにはGCPが用意しているブラウザベースのターミナルからも接続できるが、手元の環境から接続するのにgcloudが便利。

```
# 初期設定
gcloud auth login
exec -l $SHELL
gcloud init

# 設定情報確認
gcloud config list

# インスタンスへの接続（リージョンなど、デフォルトの設定がなければ対話的に聞かれる）
gcloud compute ssh {インスタンス名}
```

# KaggleのDocker

KaggleのDockerは以下のリンクにある
https://github.com/Kaggle/docker-python

インストールガイドを読むと、CPU版はGoogle Container Registoryにあるが、GPU版はまだないとのこと。一度CPU版を設定してから、gpu.Dockerfileで再設定を行うようになっている。

```
# githubからクローン
git clone git@github.com:Kaggle/docker-python.git
cd docker-python
# --gpuオプションでビルド
./build --gpu
#GCPに保存
docker tag {docker image name to be tagged} {gcp project}/{docker image name}
docker push gcr.io/{gcp project}/{docker image name}
```

gpu.Dockerfileではtensorflowやpytorchなどをインストールし直している。
Xgboostは動くが、このビルドではlightgbmは動かないので、動かすには再設定が必要。

githubのssh設定等々を毎回やるのは面倒なので、インスタンス停止時にディスクは破棄しないように設定する方がいい。

（GCPの設定項目）
インスタンスを削除したときの動作
→「ディスクを維持」に変更

インスタンス停止時の維持費はディスク100GBで一ヶ月4ドル
Standard provisioned space | $0.040
(https://cloud.google.com/compute/disks-image-pricing?hl=ja)

# 立ち上げ

このままだとcuda関係のライブラリでエラーが出るので環境変数の設定が必要
https://github.com/Kaggle/docker-python/issues/361

```
echo $LD_LIBRARY_PATH
/usr/local/nvidia/lib64:/usr/local/cuda/lib64:/usr/local/cuda/lib64/stubs
```
これだとダメなので

```
export LD_LIBRARY_PATH=/usr/local/cuda/lib64
```
が必要。毎回やるのは面倒なので

```
# コンテナ作成
docker run --runtime=nvidia --name kaggle_mod kaggle/python-gpu-build /bin/bash
# コンテナ内で設定
export LD_LIBRARY_PATH=/usr/local/cuda/lib64
# コンテナ外から止めてコミット
docker stop kaggle_mode
docker commit kaggle_mod kaggle/python-gpu-build:ld-library-path-mod
```
としてみるが、もう一回入ると

```
docker run --runtime=nvidia --name kaggle/python-gpu-build:ld-library-path-mod
echo $LD_LIBRARY?PATH
=>/usr/local/nvidia/lib64:/usr/local/cuda/lib64:/usr/local/cuda/lib64/stubs
```

と戻ってしまう。環境変数は上書きできないので、コンテナ作成時にオプションで渡す(本当はDockerfileでENV内で設定してビルドし直すべき)。

```
# -eオプションでLD_LIBRARY?PATHを上書きして作成
docker run --runtime=nvidia -e LD_LIBRARY_PATH=/usr/local/cuda/lib64 -v $PWD:/home/{user_name}/project -w=/home/{user_name}/project -p 8888:8888 --rm -it 
kaggle/python-gpu-build jupyter notebook --no-browser --ip="0.0.0.0" --notebook-dir=/home/{user_name} --allow-root
```

# GPUを使ってみる

GPUが見つかるか確認

```
# tensorflow
import tensorflow as tf
tf.contrib.eager.num_gpus()

# pytorch
import torch
torch.cuda.get_device_name(device=0)
```

XGboostを試す

```
from xgboost import XGBClassifier
clf = XGBClassifier(
        n_estimators=1000,
        max_depth=9,
        learning_rate=0.05,
        subsample=0.9,
        colsample_bytree=0.9,
        missing=-999,
        n_jobs=-1,
        random_state=42,
        tree_method="gpu_hist")
clf.fit(X_resampled,y_resampled)
```

nvidia-smiでGPUの状態を見れる

```
# リアルタイムにGPUの状態を監視
watch -n1 "nvidia-smi"

Every 1.0s: nvidia-smi                                                                                                                     machine-learning-vm: Mon Aug 12 02:47:11 2019
Mon Aug 12 02:47:11 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.104      Driver Version: 410.104      CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| 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 P100-PCIE...  Off  | 00000000:00:04.0 Off |                    0 |
| N/A   46C    P0    88W / 250W |   2833MiB / 16280MiB |    100%      Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      9329      C   /opt/conda/bin/python                       2823MiB |
+-----------------------------------------------------------------------------+
```