gcp上でTensorFlowをGPU実行

# 概要
画像系の機械学習のために、gcpでGPU環境を構築し、TensorFlowを実行しました。
今回はその備忘録です。

# 前提条件
- gcpアカウントがあること
- プロジェクト作成されていること
- GPU割り当て申請がされていること
    - ※ここは色々面倒だったので後述します。

# GPUの割り当て申請
gcpでGPU使用するには初回のみ申請が必要です。
下記2つの申請が必要です。

- グローバル GPU 割り当て 
- 使用リージョンのGPUモデルに対する割り当て 

自分の場合、
1回目に**使用リージョンのGPUモデルに対する割り当て**

| リージョン | GPUモデル |
|:-----------|:--|
| asia-east1 |tesla K80  |

2回目に**グローバル GPU 割り当て**
`GPUs (all regions)`

をそれぞれ出しています。
1度の申請でまとめて出すことも可能なようです。

申請方法ですが、既に詳細に説明されてる記事があったので、
そちらを紹介させて頂きます。

- [Google Cloud Platform + GPU設定 備忘録](https://qiita.com/Ihmon/items/03b4e24e04db29e6d0dd)
- [Leela Zero を GCE で動かす 〜 その１ Google Compute Engine 設定編](https://qiita.com/miuraken/items/e151785bc1e7f1404035)

ちなみにですが、
自分は申請してないtesla V100の上限もいつのまにか1になっており、
起動することもできました。
正直GPU割り当てについては手探りでやったので良く分かってません。

# インスタンス作成(コンソールの場合)
Compute engine -> VMインスタンス
から「作成」をクリック。
![スクリーンショット 2020-11-25 0.17.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/6b4cedf2-8903-89f8-ab0d-52b733e3889b.png)

その後、MarketPlaceをクリック。
![スクリーンショット 2020-11-25 0.18.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/767d3c8d-debb-3c3e-fddf-ace109609d4f.png)

テキストフィールドに「deep learning vm」と入力し、一番先頭に表示されるイメージをクリックします。
![スクリーンショット 2020-11-25 0.19.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/7ba9c7a0-2a42-c064-8b44-4e6db19ae0fa.png)

適用開始
![スクリーンショット 2020-11-25 0.34.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/e6f96edc-f0a5-da09-b9b7-722147c16f62.png)


一部の設定を変更後に「デプロイ」をクリックして、インスタンスを起動します。

| 項目名 | 設定例 |備考|
|:-----------|:--|:--|
| Deployment name | tf-test001 | インスタンス名です  |
| Zone | us-west1-b |  リージョン(us-west1)はGPU割り当て申請時のところにしてください。ゾーン(b)は起動したいGPUがあるところにしてください。ゾーンによっては起動できないGPUがあります |
| GPUの数 | 1 | そのまま  |
| GPUのタイプ | Tesla K80 | 特に理由がなければv100以外で選ぶのをおすすめします。v100は人気だからなのかたまにデプロイに失敗することがあります  |
| NVIDIA GPUドライバ | チェック | インスタンス起動時にNVIDIA GPUドライバを自動でインストールするかどうかです。自前で特殊なドライバを入れる場合以外はチェックを入れたほうがいいと思います。|
| Boot disk size | 200 | インスタンスのディスクサイズです。200Gより小さいと、起動後にパフォーマンスが下がると警告が出るので基本200で |

![スクリーンショット 2020-11-25 0.23.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/e5611681-0f9a-6268-5fac-493f0a140c6c.png)
![スクリーンショット 2020-11-25 1.10.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/7982161f-fb68-7274-8326-cc2c2e91a057.png)

# インスタンス作成(CLIの場合)
CLIで同様にする場合は下記になります。

```
export IMAGE_FAMILY="tf2-2-3-cu110"
export ZONE="us-west1-b"
export INSTANCE_NAME="tf-test001"
export BOOT_DISK_SIZE="200GB"
export MACHINE_TYPE="n1-highmem-2"
gcloud compute instances create $INSTANCE_NAME \
 --zone=$ZONE \
 --image-family=$IMAGE_FAMILY \
 --image-project=deeplearning-platform-release \
 --maintenance-policy=TERMINATE \
 --accelerator='type=nvidia-tesla-k80,count=1' \
 --metadata='install-nvidia-driver=True' \
 --boot-disk-size=$BOOT_DISK_SIZE \
 --machine-type=$MACHINE_TYPE
```
# ブラウザウィンドウでSSH接続
起動後、しばらく待つと
Compute engine -> VMインスタンス一覧にインスタンスが表示されます。
SSH -> ブラウザウィンドウで開く をクリック。
するとSSHのウィンドウが表示されます。
![スクリーンショット 2020-11-25 2.11.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/77cf080d-1738-2944-4d3e-6c539646bb65.png)

# GPUドライバの確認
`インスタンス起動時にNVIDIA GPUドライバをインストールする`に
チェックを入れて起動したので、すでにNVIDIA GPUドライバがインストールされています。
`nvidia-smi`コマンドで確認してみます

#### GPUドライバ入ってる場合
```
$ nvidia-smi
Tue Nov 24 15:42:42 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.51.06    Driver Version: 450.51.06    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
| N/A   43C    P0    72W / 149W |      0MiB / 11441MiB |    100%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

#### GPUドライバ入ってない場合
```
$ nvidia-smi
-bash: nvidia-smi: command not found
```

# tensorflow用のdockerを起動する
googleが用意したdeep learning向けのコンテナを起動します。
コマンドは下記です。
イメージは[deeplearning-platform-release](https://console.cloud.google.com/gcr/images/deeplearning-platform-release)から選びます。
自分は `tf2-gpu`(tensorflow2向けのGPU用イメージ)を選択してます。


```
docker run -it --rm --name tensorflow-gcp gcr.io/deeplearning-platform-release/tf2-gpu
```

実行後は自動でJupyter Labが起動します。
![スクリーンショット 2020-11-25 2.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/052dd411-0e55-8178-630b-4c76a3d27e11.png)

#SSHポートフォワーディングでJupyter Labに接続
SSHポートフォワーディングし、ローカルポートにアクセスするとJupyter Labに繋がるようにします。

```
$ gcloud compute ssh --zone {インスタンスのゾーン} "{インスタンス名}" -- -N -f -L 28888:localhost:8080
例
gcloud compute ssh --zone us-west1-b "tf-test001" -- -N -f -L 28888:localhost:8080
```

実行後は`http://localhost:28888`でJupyter Labに接続できます。
![スクリーンショット 2020-11-25 3.16.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/d2a88dbe-b300-3326-9a51-145600d2b5e9.png)

# Jupyter Labでtensorflowを実行
まずは新規のnotebookを作成
![スクリーンショット 2020-11-25 23.26.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/6f830b6d-9bd1-cc31-3f0e-44f51c2c4082.png)

次に下記コードでTensorFlowからGPU認識されているか確認します

```
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
```
![スクリーンショット 2020-11-25 23.41.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/cb4a38a2-438b-7832-eb06-9ceb50a8840c.png)
大丈夫そうです。
これでtensorflowをGPU実行できます。
[初心者のための TensorFlow 2.0 入門](https://www.tensorflow.org/tutorials/quickstart/beginner?hl=ja)を実行してみました。
![スクリーンショット 2020-11-25 23.44.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80286/19b68859-eea2-bebc-2a27-173afabdbcbd.png)

###その他の参考にした記事
- [GCP の Deep Learning VM Image を使って Deep Learning の勉強をする](https://qiita.com/chlochan/items/dec439384247b395c89f)
- [Google Cloud Platform の Compute Engine で GPU 環境を構築して TensorFlow を動作させる](https://qiita.com/chanmori/items/97dc70e063a0f2e39ba6)
- [GCPで格安のpreemptibleなGPU環境(chainer,tensorflow+python3)を30分で立ち上げる](https://qiita.com/mogamin/items/a15d9400bea3f58cca38)