画像系などでGPUを使いたくてGCE上でKaggleのコンテナイメージを使ったGPU環境をつくりました。以下自分用の備忘録となります。
- 割り当てリクエスト(はじめにやること)
- Google Compute Engineを立てる
- NVIDIA ドライバが含まれる CUDAをいれる
- コンテナ環境を作る
- Kaggle のコンテナイメージを使ってGPU環境を作る
割り当てリクエスト(はじめにやること)
最初に行うことはGPUの割り当てリクエストを送ることです。GPUをGCE上で使うためにはGoogle側に割り当てをリクエストする必要があります。
割り当てないと、GPUのドライバインストール後の確認じに以下のようなエラーがでます。
GPU の追加または削除 | Compute Engine ドキュメント | Google Cloud
Quota 'NVIDIA_P100_GPUS' exceeded. Limit: 1.0 in region us-east1.
注意事項として、割り当てリクエストは対象のGPU(例えば'NVIDIA_P100_GPUS)に加えて、
GPUグローバルリージョンでの割り当ても必要となります。割り当てないと以下のようなエラーがでます。
Quota 'GPUS_ALL_REGIONS' exceeded. Limit: 0.0 globally.
GPUグローバルリージョン
- サービス:Compute Engine API
- 名前:GPUs (all regions)
- 割り当て指標:compute.googleapis.com/gpus_all_regions
割り当てをリクエストする際用途を問われます。2日以内に審査されます。
私は最初審査が通らなかったので、サポートに問い合わせたところ通りました。
Google Compute Engineを立てる
Google Compute Engineインスタンスを立てます。リージョンとインスタンスタイプによって割り当て可能なGPUは異なります。私は次のスペックのものを選びました。GPUを追加するにはGCEの編集画面から「CPU プラットフォーム」を選び GPUよりGPUを追加する。
リージョン:1-standard-8 ゾーン:us-central1-a インスタンスタイプ:n1-standard-8 OS:Ubuntu 16.04 LTS(試せてませんが他のバージョンだとドライバのインストールがうまくいかない等の記事をみました) ディスクサイズ:500GB GPU のタイプ: NVIDIA Tesla T4(安い)
NVIDIA ドライバが含まれる CUDAをいれる
次のドキュメントにしたがってドライバとCUDAを入れます。
cloud.google.com
curl -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-ubuntu1604.pin sudo mv cuda-ubuntu1604.pin /etc/apt/preferences.d/cuda-repository-pin-600 sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/ /" sudo apt update sudo apt install cuda
次のような画面が出ればOKです。
nvidia-smi Wed Sep 30 10:50:27 2020 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 455.23.05 Driver Version: 455.23.05 CUDA Version: 11.1 | |-------------------------------+----------------------+----------------------+ | 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 V100-SXM2... Off | 00000000:00:04.0 Off | 0 | | N/A 33C P0 48W / 300W | 0MiB / 16160MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 Tesla V100-SXM2... Off | 00000000:00:05.0 Off | 0 | | N/A 33C P0 47W / 300W | 0MiB / 16160MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
コンテナ環境を作る
ここからが本題です。コンテナ側からGPUを使えるようにします。
DockerとDocker-composeをインストールしておきます。OSに合わせてUbuntuのインストール方法に従います。
- Docker
- docker-compose
バージョンを確認
19.03以降はGPUのビルド方法が異なります。今回は19.03.13で動かしています。
バージョン確認するとこんなかんじです。
sudo docker version Client: Docker Engine - Community Version: 19.03.13 API version: 1.40 Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:02:59 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.13 API version: 1.40 (minimum version 1.12) Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:01:30 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.3.7 GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683
「--gpus all」でコンテナを起動してみると次のエラーが出ます。
docker run --gpus all nvidia/cuda nvidia-smi
エラーが出た場合
次のようなエラーが出た場合はのたいしょ方について書きます。
docker: Error response from daemon: linux runtime spec devices: could not select device driver "" with capabilities: [[gpu]].
次のようなスクリプトをつくります。
vi nvidia-container-runtime-script.sh
スクリプトには以下の内容おw記載します。
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \ sudo apt-key add - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \ sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list sudo apt-get update Execute the script
$ sh nvidia-container-runtime-script.sh $ sudo apt-get install nvidia-container-runtime $ docker run -it --rm --gpus all ubuntu nvidia-smi
再起動してみます。私の場合再起動してやってのコンテナ側でGPUを認識できるようになりました。
sudo reboot
無事コンテナを起動できました。
$ sudo docker run --name notebook -t -d --gpus all -p 8888:8888 tensorflow/tensorflow:latest-gpu ________ _______________ ___ __/__________________________________ ____/__ /________ __ __ / _ _ \_ __ \_ ___/ __ \_ ___/_ /_ __ /_ __ \_ | /| / / _ / / __/ / / /(__ )/ /_/ / / _ __/ _ / / /_/ /_ |/ |/ / /_/ \___//_/ /_//____/ \____//_/ /_/ /_/ \____/____/|__/ WARNING: You are running this container as root, which can cause new files in mounted volumes to be created as the root user on your host machine. To avoid this, run the container by specifying your user's userid: $ docker run -u $(id -u):$(id -g) args...
sudo docker exec -it notebook bash root@db527145397e:/# pip install jupyter root@db527145397e:/# jupyter notebook --port 8888 --ip=0.0.0.0 --allow-root
コンテナからGPUの動作確認
コンテナで認識できてるかノートブックから確認してみます。
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
次のような結果であれば大丈夫です。
... incarnation: 17636037438262103350 physical_device_desc: "device: XLA_GPU device", name: "/device:XLA_GPU:1" device_type: "XLA_GPU" memory_limit: 17179869184 locality { } ....
Kaggle のコンテナイメージを使ってGPU環境を作る
ここまででコンテナを使ってGPU環境を使いました。ただし、使いたいライブラリとかいれるのが少しめんどくさいのでノートブックはKaggleのを使いたいと思います。
KaggleのイメージでGPUを使いたい場合は現時点だとビルドしてイメージを作る必要があります。
Kaggleではイメージをビルドする必要があります。
# clone git clone https://github.com/Kaggle/docker-python.git cd docker-python # --gpuオプションでビルド sudo ./build --gpu # イメージを確認 $ sudo docker image ls
次のようなイメージが作られてると思います。(結構時間かかります)
$ sudo docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE kaggle/python-gpu-build latest 2f9b2c1b22f0 45 hours ago 26.8GB tensorflow/tensorflow latest-gpu 8a8486aa1902 3 days ago 3.05GB gcr.io/kaggle-images/python staging f21a22cf6451 3 days ago 17.6GB nvidia/cuda 10.0-cudnn7-devel-ubuntu16.04 925d6a4390fd 3 weeks ago 3.28GB gcr.io/kaggle-images/python-tensorflow-whl 2.3.0-py37 5b7404d41bb2 2 months ago 14.4GB gcr.io/kaggle-images/python v78 bccb00c5ef95 3 months ago 16.6GB
docker-compose.ymlの定義
ビルドしたKaggleのコンテナイメージを参照する次のようなymlをつくります。
version: "2.4" services: jupyter: image: kaggle/python-gpu-build:latest # tensorflow/tensorflow:latest-gpu container_name: notebook runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=all volumes: - ./:/home working_dir: /home ports: - 8888:8080 command: jupyter notebook --ip=0.0.0.0 --allow-root --no-browser # sudo docker exec -it notebook jupyter notebook list
こんなエラーが出た場合
パラメータで渡してるruntime: nvidiaでエラーが出るケースです、
Unsupported config option for services.jupyter: 'runtime'
次の記事によるとdocker-composeの場合は設定ファイルをつくり実行する必要があるようです。
> docker-compose の場合 2019/11/29 現在、docker-compose では Docker の --gpus と同等のオプションはサポートされていないようです。そのため、別途 nvidia-container-runtime をインストールして、/etc/docker/daemon.json に設定ファイルを作成します。
sudo apt-get install nvidia-container-runtime
sudo tee /etc/docker/daemon.json <<EOF { "runtimes": { "nvidia": { "path": "/usr/bin/nvidia-container-runtime", "runtimeArgs": [] } } } EOF sudo pkill -SIGHUP dockerd
https://blog.mahoroi.com/posts/2019/12/docker-gpus-nvidia/
github.com
私の場合はバージョンが要因で同様にruntimeオプションを選べませんでした。2.4で動くようになりました。
version: "3.2" → version: "2.4"
起動して動作確認を行います。
$ sudo docker-compose up -d --build
動作確認
コンテナ側でGPUを認識できてることを確認します。
from tensorflow.python.client import device_lib device_lib.list_local_devices()
... incarnation: 17636037438262103350 physical_device_desc: "device: XLA_GPU device", name: "/device:XLA_GPU:1" device_type: "XLA_GPU" memory_limit: 17179869184 locality { } .... >>>
import pandas as pd import numpy as np import json import tensorflow.keras.layers as L import keras.backend as K import tensorflow as tf import plotly.express as px from sklearn.model_selection import StratifiedKFold, KFold, GroupKFold from sklearn.cluster import KMeans import os os.environ['CUDA_VISIBLE_DEVICES'] = '0' def allocate_gpu_memory(gpu_number=0): physical_devices = tf.config.experimental.list_physical_devices('GPU') if physical_devices: try: print("Found {} GPU(s)".format(len(physical_devices))) tf.config.set_visible_devices(physical_devices[gpu_number], 'GPU') tf.config.experimental.set_memory_growth(physical_devices[gpu_number], True) print("#{} GPU memory is allocated".format(gpu_number)) except RuntimeError as e: print(e) else: print("Not enough GPU hardware devices available") allocate_gpu_memory()
Found 1 GPU(s) #0 GPU memory is allocated
コンテナ側でGPUを認識できてるので大丈夫そうです。