こんにちは。アドバンストテクノロジー部のR&Dチーム所属岩原です。
好きなKerasのLayerはDropoutです。
今回は、docker上でNVIDIA製GPUを使ったディープラーニング環境を構築してくれるnvidia-docker
の紹介と、nvidia-docker
を Docker-compose
で使用する方法を導入から紹介したいと思います。
nvidia-dockerとは
Docker上でCUDAやcuDNNを使えるようにしたNVIDIA製のDockerプラグインです。
NVIDIA/nvidia-docker: Build and run Docker containers leveraging NVIDIA GPUs
Tensorflow-gpuがDocker上で動かせるようになるため、環境を選ばず(といってもNVIDIA製GPUは必要ですが)どこでもTensorflowやKerasをぶん回すことができるようになります。
ただし、nvidia-dockerを実行する場合、通常は以下のようなコマンドで実行します。
nvidia-docker run --rm nvidia/cuda nvidia-smi
この場合、docker-composeではnvidia-dockerが使えない事になります。
eywalker/nvidia-docker-compose: Simple wrapper for docker-compose to use GPU enabled docker under nvidia-dockerのようなdocker-composeを拡張したモジュールもありますが、
今回はそのような物をインストールせず、手軽に対応する方法をご紹介したいと思います。
まずは導入から始めましょう。
環境
- OS:Ubuntu 16_04 LTS
- GPU:GTX 1080 Ti 11GB
- GPUは最近のNVIDIA製GPUであれば問題はないかと思います。
GPUのアーキテクチャがKepler
であれば最新のCUDA9にも対応しています。
- GPUは最近のNVIDIA製GPUであれば問題はないかと思います。
CUDA(& Driver)のインストール
nvidia-dockerにCUDAは本来必要ないのですが、ドライバー単体のインストールは面倒なので、CUDAもついでにインストールしてしまいます。
ドライバー単体はNVIDIAドライバダウンロードからダウンロード出来ます。
今回はCUDAのインストール手順をご紹介します。
手順
-
CUDA Toolkit Download | NVIDIA Developerより
Linux
->x86_64
->Ubuntu
->16.04
->deb(network)
を選びます。- Tensorflowを使う場合はCUDA8が推奨されているため、もし、ホストマシンでTensorflowを実行したいのであれば、CUDA Toolkit 8.0 - Feb 2017 | NVIDIA Developerから同じ手順で選択してください。なお、CUDA Toolkit Archive | NVIDIA Developerから他のバージョンも選択できます。
- Downloadのリンクアドレスをコピーします。
-
http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.0.176-1_amd64.deb
のようなURLになっているはずです。バージョンによってURLは変わります。
-
-
wget 2.でコピーしたURL
でダウンロードします。 - 以下、
Installation Instructions
に沿ってコマンドを実行していきます。このあたりはCUDAのバージョンによって変わってくるので、画面の指示に従いましょう。以下は2017/11/2時点での最新の場合のコマンドになります。なお、最後に再起動するコマンドを追加しています。
sudo dpkg -i cuda-repo-ubuntu1604_9.0.176-1_amd64.deb sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub sudo apt-get update sudo apt-get install cuda sudo reboot
エラーが出た場合
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
上記実行時、
gpgkeys: protocol `https' not supported
というメッセージが出る場合があります。
この場合、
sudo apt-get install gnupg-curl
を実行した上で、再度コマンド実行すればOKです。
動作確認
nvidia-smi
コマンドがエラーにならなければ正常にインストールされたことになります。
Dockerのインストール
古いDockerの削除(Docker CEになる前にdockerをインストールした人のみ)
sudo apt-get remove docker docker-engine docker.io
で古いDockerを削除します。
手順
-
必要なパッケージのインストール
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
で必要なパッケージのインストールを行います。 -
GPGキーの取得
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
でDocker公式のGPGキーを取得&追加します。 -
リポジトリの追加
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
でリポジトリの追加を行います。
今回はstable
ですがtest
やedge
と言ったバージョンも指定できます。 -
パッケージの更新
sudo apt-get update
でパッケージの更新を再度行います。 -
Docker CEのインストール
sudo apt-get install docker-ce
でdockerのインストールを行います。 -
動作確認
sudo docker run hello-world
でHello from Docker!
が表示されれば問題なくインストールされています。
nvidia-dockerのインストール
wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb
コレだけです。
nvidia-dockerを動かしてみる
nvidia-docker run --rm nvidia/cuda nvidia-smi
を実行し、GPUドライバの情報が出力されれば、インストールは成功です。
Docker-composeのインストール
手順
以下のコマンドを実行します。
sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-uname -s
-uname -m
-o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
docker-compose version 1.16.1, build 1719ceb
のような表示がされればOKです。
Docker-composeで動かす方法
さて、本題の docker-compose
コマンドでnvidia-dockerを動かす方法です。
先にdocker-compose.ymlを示します。
version: "3" services: tensorflow_keras: build: dockerfile: Dockerfile volumes: - nvidia_driver_384.90:/usr/local/nvidia:ro devices: - /dev/nvidiactl - /dev/nvidia-uvm - /dev/nvidia0 volumes: nvidia_driver_384.90: external: true
volumes
でドライバを、devices
でGPUなどを指定してやる形になります。
nvidia_driver_384.90
の部分はインストールされているドライバのバージョンによって変わります。nvidia-smi
コマンドを実行して確認しましょう。
nvidia-smi Mon Nov 6 07:14:16 2017 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 384.90 Driver Version: 384.90 | |-------------------------------+----------------------+----------------------+
nvidia-docker
を実行した際、必要なvolumeが作られてなければ自動作成されますが、
そうでない場合、以下のコマンドを実行し、自分でvolumeを作成してやる必要があります。
docker volume create --name=nvidia_driver_384.90 -d nvidia-docker
nvidia_driver_384.90
の 384.90
はドライバーのバージョンによって変わりますので、適宜変えるようにしてください。
docker volume ls
コマンドでDRIVER
が nvidia-docker
になっているものが存在していればOKです。
docker volume ls | grep nvidia-docker nvidia-docker nvidia_driver_384.90
実際に動かしてみる
それでは、実際にnvidia-docker上で動かしてみましょう。
Kerasのサンプルの1つである、mnist + CNNを動かすDockerイメージを作ります。
keras/mnist_cnn.py at master · fchollet/keras
まず、ディレクトリ構造を以下の通りとします。
. ├── docker-compose.yml └── tensorflow_keras ├── Dockerfile ├── entrypoint.sh ├── mnist_cnn.py └── requirements.txt
上から順に記載していきます。
docker-compose.yml
ほぼ先ほど紹介した内容に沿います。Dockerfileのディレクトリだけ違うので、それだけ追加しています。
version: "3" services: tensorflow_keras: build: context: ./tensorflow_keras dockerfile: Dockerfile volumes: - nvidia_driver_384.90:/usr/local/nvidia:ro devices: - /dev/nvidiactl - /dev/nvidia-uvm - /dev/nvidia0 volumes: nvidia_driver_384.90: external: true
tensorflow_keras/Dockerfile
Tensorflowを使用するため、CUDA8 + CuDNN6の組み合わせのdockerイメージをベースに使用します。
OSはホストと同じUbuntu16.04を使用します。
FROM nvidia/cuda:8.0-cudnn6-runtime-ubuntu16.04 RUN apt-get update && \ apt-get -y install wget build-essential gcc zlib1g-dev openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev libmecab-dev mecab mecab-ipadic-utf8 # setup Python3.6 WORKDIR /tmp RUN wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz \ && tar zxf Python-3.6.1.tgz \ && cd Python-3.6.1 \ && ./configure \ && make altinstall ENV PYTHONIOENCODING "utf-8" # pip install COPY requirements.txt /tmp RUN pip3.6 install -r /tmp/requirements.txt RUN python3.6 --version # setup my script RUN mkdir /var/tensorflow_keras COPY mnist_cnn.py /var/tensorflow_keras WORKDIR /var/tensorflow_keras # setup endpoint COPY entrypoint.sh ./ RUN chmod +x ./entrypoint.sh ENTRYPOINT ./entrypoint.sh
tensorflow_keras/entrypoint.sh
実行の確認さえできればいいので、Pythonスクリプトを実行するだけです。
無限待ちしたい場合は最後の tail -f /dev/null
のコメントアウトを外します。
#! /bin/bash python3.6 mnist_cnn.py # tail -f /dev/null
tensorflow_keras/mnist_cnn.py
Kerasを使用してmnistの学習を行う簡単なサンプルです。
keras/mnist_cnn.py at master · fchollet/kerasからそのまま持ってきましょう。
requirements.txt
必要なPythonライブラリ群を記したものです。
現在の弊社環境のものを記載します。不要なものも混じってますが、参考までに。
基本的に、kerasとtensorflow-gpuのみ pip install
すれば良いはずです。
bleach==1.5.0 h5py==2.7.1 html5lib==0.9999999 Keras==2.0.8 Markdown==2.6.9 numpy==1.13.1 pandas==0.20.3 protobuf==3.4.0 python-dateutil==2.6.1 pytz==2017.2 PyYAML==3.12 scikit-learn==0.19.0 scipy==0.19.1 six==1.10.0 tensorflow-gpu==1.3.0 tensorflow-tensorboard==0.1.6 Werkzeug==0.12.2 mecab-python3==0.7
実行結果
まずはイメージのビルドをします。
docker-compose build
次に実行します。
docker-compose up
すると、大量の出力とともに、結果が以下のように出力されるはずです。
〜〜〜〜 省略 〜〜〜〜 tensorflow_keras_1 | Epoch 10/12 60000/60000 [==============================] - 3s - loss: 0.0383 - acc: 0.9886 - val_loss: 0.0311 - val_acc: 0.9900 tensorflow_keras_1 | Epoch 11/12 60000/60000 [==============================] - 3s - loss: 0.0380 - acc: 0.9887 - val_loss: 0.0292 - val_acc: 0.9901 tensorflow_keras_1 | Epoch 12/12 60000/60000 [==============================] - 3s - loss: 0.0347 - acc: 0.9897 - val_loss: 0.0291 - val_acc: 0.9903 tensorflow_keras_1 | Test loss: 0.0291294318363 tensorflow_keras_1 | Test accuracy: 0.9903 tensorflow_keras_1 | Using TensorFlow backend. tensorflow_keras_1 exited with code 0
ちなみに、GPUが使われているかどうかを判断するには、以下の出力があるかどうかでわかります。
tensorflow_keras_1 | 2017-11-02 06:12:18.275339: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:01:00.0)
docker-compose.ymlの記述が間違っていたりすると、
tensorflow_keras_1 | 2017-11-02 06:16:04.237736: E tensorflow/stream_executor/cuda/cuda_driver.cc:406] failed call to cuInit: CUDA_ERROR_NO_DEVICE
のような出力がされたり、CPUが使われるようになるので、以下のように学習時間がとても長くなったりします。
tensorflow_keras_1 | Epoch 1/12 60000/60000 [==============================] - 74s - loss: 0.3219 - acc: 0.9015 - val_loss: 0.0803 - val_acc: 0.9744
上記の例では、1epochで74sec掛かってることになります。およそ25倍時間がかかってます。
複数のGPUを持つマシンで、GPUを指定したい
以下のような構成の場合(例:AWSのp2.8xlarge)
ls -la /dev | grep nvidia crw-rw-rw- 1 root root 195, 0 Nov 6 05:51 nvidia0 crw-rw-rw- 1 root root 195, 1 Nov 6 05:51 nvidia1 crw-rw-rw- 1 root root 195, 2 Nov 6 05:51 nvidia2 crw-rw-rw- 1 root root 195, 3 Nov 6 05:51 nvidia3 crw-rw-rw- 1 root root 195, 4 Nov 6 05:51 nvidia4 crw-rw-rw- 1 root root 195, 5 Nov 6 05:51 nvidia5 crw-rw-rw- 1 root root 195, 6 Nov 6 05:51 nvidia6 crw-rw-rw- 1 root root 195, 7 Nov 6 05:51 nvidia7 crw-rw-rw- 1 root root 195, 255 Nov 6 05:51 nvidiactl crw-rw-rw- 1 root root 247, 0 Nov 6 05:51 nvidia-uvm crw-rw-rw- 1 root root 247, 1 Nov 6 05:52 nvidia-uvm-tools
GPUが複数存在する事になります。
この場合、nvidia-dockerで使用するGPUを指定することが可能です。
docker-compose.ymlのdevices
を使用したいGPUにしてやることで可能となります。
version: "3" services: tensorflow_keras: build: context: ./tensorflow_keras dockerfile: Dockerfile volumes: - nvidia_driver_384.90:/usr/local/nvidia:ro devices: - /dev/nvidiactl - /dev/nvidia-uvm - /dev/nvidia1 # ココ! volumes: nvidia_driver_384.90: external: true
また、複数指定してやることも可能です。
version: "3" services: tensorflow_keras: build: context: ./tensorflow_keras dockerfile: Dockerfile volumes: - nvidia_driver_384.90:/usr/local/nvidia:ro devices: - /dev/nvidiactl - /dev/nvidia-uvm - /dev/nvidia2 # ココ! - /dev/nvidia1 # ココ! volumes: nvidia_driver_384.90: external: true
tensorflowでちゃんと複数認識します
tensorflow_keras_1 | 2017-11-06 07:29:00.244487: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:00:18.0) tensorflow_keras_1 | 2017-11-06 07:29:00.244501: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:1) -> (device: 1, name: Tesla K80, pci bus id: 0000:00:19.0)
使用するGPUを割り振ることで、複数Dockerでも効率よく学習を行うことが出来ます。
まとめ
ホストマシンの環境に左右されてしまうところはありますが、環境さえ合わせてしまえば複数マシンで同じイメージが使用できるので、
ディープラーニング環境のポータビリティがよくなります。
また、バージョン違いのTensorflowも1つのマシンで共有できるので、1台のマシンで複数バージョンのCUDAを使用したい場合などに重宝します。