【2019年9月現在】GCE+Tensorflow-GPU 1.13.1(テスト済みのビルド設定) 環境構築

前回、[GCE（Google Compute Engine）とCloud Storageとの連携](https://qiita.com/obegk/items/d1cbbfc7e2a1d790b39d)について記載しましたが、今回はその環境を使用して ```tensolflow-gpu``` 環境を作成します。

# 環境
- Ubuntu 18.04
- pipenv 2018.11.26
- Tensorflow-gpu 1.13.1
- NVIDIA Driver 410.104
- CUDA 10.0
- cuDNN 7.4.2

# 注意事項
- GPUの割り当ては、無料トライアル期間中では使用できないサービスなので、GPUの割り当て申請とともに無料トライアルが終了します。無料トライアルで使える「CPU 8つ」の環境で足りなくなった際に導入を検討してみてください。価格の試算は[こちら](https://cloud.google.com/products/calculator/?authuser=3&hl=ja)からできます。
- Tensorflow-gpuは互換性がシビアなので、必ずTensorflow-gpuの[テスト済みビルド設定の一覧](https://www.tensorflow.org/install/source?hl=ja#linux)を確認してから導入を検討してください。

### 追記(2019年9月5日)

- 有料アカウント移行後も残っている$300クレジットは使用できます。
- 無料トライアル期間中であればサービスを停止し、それ以上の課金がされません。有料アカウントの詳細は[こちら](https://cloud.google.com/free/docs/gcp-free-tier?hl=ja#how-to-upgrade)から確認できます。

# 全体の流れ
1. GPUの割り当て
2. インスタンスの作成
3. pipenvおよびライブラリのインストール
4. ```tensorflow-gpu``` に必要なライブラリをインストール
5. GPUの動作確認


# 1.GPUの割り当て

GCEのインスタンス上でGPUを使用するには、割り当ての申請を行う必要があります。
[こちら](https://tech.zeals.co.jp/entry/2019/01/08/094054)のサイト様を参考にさせていただきました。
審査は数時間ほどで済みますが、場合によっては2日ほど時間がかかるケースもあるかもしれません。

## 割り当て申請

他サイト様で画像付きでまとめられているので、本記事では流れだけ文面で掲載いたします。

1. 「IAMと管理」を開く
2. 「割り当て」を選択
3. 「指標」のプルダウンを開き、「なし」を選択
4. 「指標」の検索フォームに「GPU」を入力
5. 「GPUs (all regions)」にチェックを入れる
6. 「編集の割り当て」をクリック
7. 「Compute Engine API GPUs (all regions)」の左側にチェックを入れる。
8. 連絡先を入力し、次へ
9. 使用予定のGPUの数と、使用目的（英語）を入力して完了。

以上で申請は終了です。
後ほど、Google Cloud Supportより割り当ての申請の承諾メールが届きます。

# 2.インスタンスの作成

こちらの手順でインスタンスを作成します。
https://cloud.google.com/compute/docs/quickstart-linux?hl=ja

今回使用するインスタンスの設定は以下の通りです。マシンタイプは用途によって変更してください。
リージョンおよびゾーンによって、GPUが使用できない場合があるのでご注意ください。

```
リージョン： us-east1
ゾーン：us-east1-c
マシンタイプ：n1-highmem-8 (8 vCPU、 52GB メモリ)
GPUの数： 1
GPUのタイプ： NVIDIA Tesla K80
ブートディスク： Ubuntu 18.04 LTS （SSD 永続ストレージ：15GB）
サービスアカウント： Compute Engine default service account（デフォルト）
アクセススコープ： 各 API にアクセス権を設定（ストレージ：フル）
```

# 3.仮想環境の作成、ライブラリのインストール

Tensorflowのバージョンを指定したいので、今回はpipとvirtualenvを手軽に使える ```pipenv``` を使用していきます。

```bash
# install pip3
sudo apt-get install -y python3-pip
# install pipenv
pip3 install pipenv
sudo reboot
```

プロジェクトフォルダを作成し、仮想環境を作成。
※lockファイルはタイムアウトの原因になるので、今回は使用しません。

```bash
# make pipenv project
mkdir ml
cd ml
pipenv install tensorflow-gpu==1.13.1 pandas numpy matplotlib keras ipykernel graphviz pydot --skip-lock
# use virtualenv
pipenv shell
```

仮想環境を削除する際は、以下のコマンドを実行。

```bash
# at project folder
# find pipenv location
pipenv --venv
# remove venv
pipenv --rm
```

# 4.tensorflow-gpu に必要なライブラリをインストール

TensorFlowの[テスト済みのビルド設定](https://www.tensorflow.org/install/source#linux)を参考に、以下の構成でライブラリをインストールする。

- tensorflow：tensorflow_gpu-1.13.1
- python：3.6
- cuDNN：7.4
- CUDA：10.0
- コンパイラ・ビルドツール（GCC,Bazel）

また上記とは別に、使用するGPUに対応したドライバーをインストールする必要がある。
今回は```NVIDIA Tesla K80``` を使用するので、NVIDIAドライバーをインストールする。

## コンパイラ・ビルドツールをインストール

```bash
sudo apt-get install -y build-essential
sudo apt-get install -y gcc
sudo apt-get install -y make
```

インストールが完了したら、再起動します。

```bash
sudo reboot
```

## NVIDIAドライバーのインストール

NVIDIAの[ドライバダウンロードページ](https://www.nvidia.co.jp/Download/index.aspx?lang=jp)より、インストーラをダウンロード。

以下の設定で検索。

```
製品のタイプ:Tesla
製品シリーズ:K-Series
製品ファミリー:Tesla K80
オペレーティングシステム:Linux 64-bit
CUDA Toolkit:10.0
言語:Japanese
```

「ダウンロード」をクリックし、次に表示されるページにてダウンロード。
```wget [URL]```を使用して、runファイルをダウンロードし、以下のコマンドでインストール。

```bash
wget http://jp.download.nvidia.com/tesla/410.104/NVIDIA-Linux-x86_64-410.104.run
chmod +x NVIDIA-Linux-x86_64-410.104.run
sudo ./NVIDIA-Linux-x86_64-410.104.run
```

インストーラーが起動するので、指示に従ってインストールして完了。
※インストール時に以下の2つの警告が表示されることがありますが、無視しても問題ないようです。
参考：GPU カードドライバーのインストール https://support.kagoya.jp/gput/manual/driver/index.html

```
nvidia-installer was forced to guess the X library path '/usr/lib' and X module path '/usr/lib/xorg/modules'; these paths were not queryable from the system.  If   
   X fails to find the NVIDIA X driver module, please install the `pkg-config` utility and the X.Org SDK/development package for your distribution and reinstall the           
   driver. 
```

```
  WARNING: Unable to find a suitable destination to install 32-bit compatibility libraries. Your system may not be set up for 32-bit compatibility. 32-bit compatibility       
  files will not be installed; if you wish to install them, re-run the installation and set a valid directory with the --compat32-libdir option.                               
```

## CUDAのインストール

Cuda Toolkitのアーカイブからバージョンが一致するものをダウンロード
https://developer.nvidia.com/cuda-toolkit-archive

今回は```CUDA Toolkit 10.0 (Sept 2018)``` を選択し、以下の設定でダウンロード。

```bash
Operating System:Linux
Architecture:x86_64
Distribution:Ubuntu
Version:18.04
Installer Type:deb(local) 
```

```Base Installer``` を以下の手順でインストール。

```bash
wget https://developer.nvidia.com/compute/cuda/10.0/Prod/local_installers/cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48_1.0-1_amd64
sudo dpkg -i cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48_1.0-1_amd64
sudo apt-key add /var/cuda-repo-10-0-local-10.0.130-410.48/7fa2af80.pub
sudo apt-get update
sudo apt-get install -y cuda
```

パッチファイルがあるので、同様の手順でインストール。

```bash
wget http://developer.download.nvidia.com/compute/cuda/10.0/Prod/patches/1/cuda-repo-ubuntu1804-10-0-local-nvjpeg-update-1_1.0-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1804-10-0-local-nvjpeg-update-1_1.0-1_amd64.deb
sudo apt-key add /var/cuda-repo-10-0-local-10.0.130-410.48/7fa2af80.pub
sudo apt-get update
sudo apt-get install -y cuda
```

参考
- Ubuntu 16.04 をインストールして NVIDIAドライバ (410.48)と CUDA10.0 と cuDNN7.4.1 を入れて Tensorflow-gpu を動かすメモ https://qiita.com/konzo_/items/3e2d1d7480f7ef632603

## cuDNNのインストール

[公式サイト](https://developer.nvidia.com/cudnn)の「Download cuDNN > Archived cuDNN Releases」からダウンロード（会員登録が必要）
※プロキシ環境でつながらない場合は、スマホなど別回線で接続を試みることをお勧めします。

以下の3つをダウンロードして、インスタンス上にアップロード。
（SSHのコンソール画面から、右上の歯車マークよりアップロードできます）

- cuDNN Runtime Library for Ubuntu18.04 (Deb)
- cuDNN Developer Library for Ubuntu18.04 (Deb)
- cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)

```sudo dpkg -i``` を使ってインストール。（上から順番にインストールすること）

```bash
sudo dpkg -i libcudnn7_7.4.2.24-1+cuda10.0_amd64.deb
sudo dpkg -i libcudnn7-dev_7.4.2.24-1+cuda10.0_amd64.deb
sudo dpkg -i libcudnn7-doc_7.4.2.24-1+cuda10.0_amd64.deb
```

参考
- Ubuntu16.04にCUDAとcuDNN入れるまでの設定メモ ~ GPU版xgboost導入まで https://futurismo.biz/archives/6864/#nvidia-cudnn-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB-nvidia-cudnn-


## インストールしたライブラリのバージョン確認

```bash
nvidia-smi
```

今回利用している```NVIDIA Tesla K80``` が認識されていれば、ひとまずOKです。

# 5.GPUの動作確認

仮想環境を起動し、Pythonのコンソールを起動

```bash
# at pipenv project folder
pipenv shell
python
```

コンソール上で、以下のコマンドを入力

```python
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
```

正しく実行できた場合

```bash
incarnation: 8451937778054707288
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 11877833915023157980
physical_device_desc: "device: XLA_GPU device"
, name: "/device:XLA_CPU:0"
device_type: "XLA_CPU"
memory_limit: 17179869184
locality {
}
incarnation: 5153049444667961496
physical_device_desc: "device: XLA_CPU device"
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 11326753997
locality {
  bus_id: 1
  links {
  }
}
incarnation: 15951891540360578159
physical_device_desc: "device: 0, name: Tesla K80, pci bus id: 0000:00:04.0, compute capability: 3.7"
```

CPUしか認識できていない場合は、GPUとTensorflowとの連携がうまくいっていないので、ライブラリの依存関係などを確認してみてください。

# まとめ

ほかのライブラリと違って、以下の点でインストールに時間がかかってしまった。

- カーネルのバージョンとの互換性
- GPUとドライバとの互換性
- ライブラリ同士の互換性
- 希望のバージョンのライブラリが```apt-get``` や ```conda``` でバージョン指定してダウンロードするのが難しい
- ```conda``` がよしなにやってくれると思いきや、思いのほか今回の環境とミスマッチだった
- cuDNNのアーカイブから特定のバージョンをダウンロードするのには会員登録が必要

Tensorflow-gpuの導入で互換性の問題でつまづいている方の助けになれば幸いです。

以上