dockerでGPUディープラーニング(TensorFlow+Keras)を構築した

どうも、TOMOZO(@TOMOZO)です。

前回GPUディープラーニング環境を構築した記事を書きました。

GPUディープラーニング環境(CUDA+cuDNN+TensorFlow+Keras)を構築した

2019.02.23

今回同じ環境をnvidia-dockerで作りました。
これでシステム環境を汚さずにpython、CUDA、cuDNN、tf、kerasの複数バージョンの平行運用が可能になります!

スポンサーリンク

ホスト環境

  • Ubuntu 18.04.1 LTS(Linux Kernel 4.15.0-43-generic)
  • NVIDIA GeForce GTX 1060
  • NVIDIAドライバ 390.77

要件

構築手順

Dockerのインストール

Dockerの公式ページに従い、インストールします。

docker-composeのインストール(必須ではない)

Dockerの公式ページに従い、インストールします。

nvidia-docker2のインストール

NVIDIAの公式ページに従い、インストールします。

いちど動作確認します。
nvidia-docker2からは--runtime=nvidia指定となってます。

$ docker run --runtime=nvidia --rm nvidia/cuda:9.0-cudnn7-devel nvcc --version
Unable to find image 'nvidia/cuda:9.0-cudnn7-devel' locally
9.0-cudnn7-devel: Pulling from nvidia/cuda
18d680d61657: Already exists
0addb6fece63: Already exists
78e58219b215: Already exists
eb6959a66df2: Already exists
6ef1ff668c93: Already exists
f5f8f0544aa2: Already exists
3d28d96eb352: Already exists
1b48d63763c4: Pull complete
70fb71aabe87: Pull complete
a547457bef7c: Pull complete
Digest: sha256:b3019fa14ee445007624ed30cdfcabf21b1fbd40c8ea559c9476a87dfcb69e06
Status: Downloaded newer image for nvidia/cuda:9.0-cudnn7-devel
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Sep__1_21:08:03_CDT_2017
Cuda compilation tools, release 9.0, V9.0.176

GPUディープラーニング環境入りdockerコンテナ作成

ベースのイメージはNVIDIAのDockerHubから、tensorflow_gpuの対応バージョンに合わせて、CUDA9.0/cuDNN7としました。

pyhon環境はpyenvで揃えます。

ついでに「Jupyter Notebook」も入れておきます。
anacondaもしくはminicondaでも良いが、どうせ仮想だし、イメージサイズが膨れるし、何をインストールしているのかもわからないから、必要に応じてpipでインストールしていくこととします。

Dockerfileはこんな感じで出来上がりました。
ただし、ベースのイメージにインストールされているcuDNNではうまくいかなかったので、ダウングレードしています。

FROM nvidia/cuda:9.0-cudnn7-devel

LABEL maintainer "thatta"

# Set environment
ENV TERM xterm
ENV LC_ALL=C.UTF-8
ENV LANG C.UTF-8

# Install apt package.
RUN DEBIAN_FRONTEND=noninteractive \
    apt-get update -y && apt-get install -y --no-install-recommends \
    apt-utils \
    less \
    wget \
    curl \
    git \
    graphviz \
    unzip \
    bzip2 \
    build-essential \
    vim \
    libncursesw5-dev \
    libgdbm-dev \
    libc6-dev \
    zlib1g-dev \
    libsqlite3-dev \
    tk-dev \
    libssl-dev \
    openssl \
    libbz2-dev \
    libreadline-dev

# Install pyenv.
RUN git clone https://github.com/pyenv/pyenv.git /opt/pyenv && \
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc
ENV PYENV_ROOT /opt/pyenv
ENV PATH $PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH
RUN $PYENV_ROOT/plugins/python-build/install.sh

# Create python 3.6 environment and install pipenv.
RUN pyenv install 3.6.0 && \
    pyenv global 3.6.0 && \
    eval "$(pyenv init -)"

# Upgrade pip.
RUN pip install --upgrade pip

# Install python library.
RUN pip install --ignore-installed \
    keras==2.2.4 \
    h5py \
    jupyter \
    matplotlib \
    notebook \
    NumPy \
    pandas \
    pydot \
    scikit-learn \
    SciPy \
    tensorflow_gpu==1.12.0 \
    jupyter_contrib_nbextensions

# Enable nbextension.
RUN jupyter contrib nbextension install --user

# Downgrade cuDNN library.
# TensorFlows issue: https://github.com/tensorflow/tensorflow/issues/17566#issuecomment-372490062
# RUN apt-get install -y --allow-downgrades --allow-change-held-packages libcudnn7=7.0.5.15-1+cuda9.0
RUN DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --allow-downgrades --allow-change-held-packages libcudnn7=7.1.4.18-1+cuda9.0

# Clean cache.
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /tmp/*

EXPOSE 8888

# Run jupyter notebook.
CMD ["jupyter", "notebook", "--allow-root", "--port=8888", "--ip=0.0.0.0"]

コンテナ操作用にMakefileも作りました。

IMAGE=nvdocker-keras
VERSION=1.0.0
CONTAINER=nvdocker-keras

build:
	docker build -t $(IMAGE):$(VERSION) .

restart: stop start

start:
	docker run \
		--runtime=nvidia \
		-itd \
		-p 8888:8888 \
		-v $(HOME):$(HOME) \
		-v /etc/localtime:/etc/localtime:ro \
		--name $(CONTAINER) \
		--workdir=`pwd` \
		$(IMAGE):$(VERSION)

contener=`docker ps -a | grep $(CONTAINER) | awk '{print $$1}'`
image=`docker images | grep $(IMAGE) | grep $(VERSION) | awk '{ print $$3 }'`

clean: rm
	@if [ "$(image)" != "" ] ; then \
		docker rmi $(image); \
	fi

rm:
	@if [ "$(contener)" != "" ] ; then \
		docker rm -f $(contener); \
	fi

stop:
	@if [ "$(contener)" != "" ] ; then \
		docker rm -f $(contener); \
	fi

attach:
	docker exec -it $(CONTAINER) bash

logs:
	docker logs $(CONTAINER)

Kerasの動作確認

イメージをビルドしコンテナにログインして、Kerasの動作確認します。
3GB強のイメージとなってます。

$ make build
$ make start
$ make attach
# ↓↓↓ここからコンテナ内での操作↓↓↓
$ git clone https://github.com/fchollet/keras.git
$ cd keras/examples
$ time python mnist_cnn.py
Using TensorFlow backend.
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
2019-01-16 10:09:03.566978: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-01-16 10:09:03.648992: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:964] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2019-01-16 10:09:03.649451: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties:
name: GeForce GTX 1060 6GB major: 6 minor: 1 memoryClockRate(GHz): 1.759
pciBusID: 0000:01:00.0
totalMemory: 5.93GiB freeMemory: 5.73GiB
2019-01-16 10:09:03.649483: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0
2019-01-16 10:09:03.820653: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-01-16 10:09:03.820704: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988]      0
2019-01-16 10:09:03.820713: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0:   N
2019-01-16 10:09:03.820999: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5505 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060 6GB, pci bus id: 0000:01:00.0, compute capability: 6.1)
60000/60000 [==============================] - 8s 134us/step - loss: 0.2614 - acc: 0.9212 - val_loss: 0.0575 - val_acc: 0.9807
Epoch 2/12
60000/60000 [==============================] - 7s 115us/step - loss: 0.0929 - acc: 0.9729 - val_loss: 0.0412 - val_acc: 0.9861
Epoch 3/12
60000/60000 [==============================] - 7s 117us/step - loss: 0.0700 - acc: 0.9791 - val_loss: 0.0350 - val_acc: 0.9882
Epoch 4/12
60000/60000 [==============================] - 7s 117us/step - loss: 0.0558 - acc: 0.9833 - val_loss: 0.0371 - val_acc: 0.9873
Epoch 5/12
60000/60000 [==============================] - 7s 118us/step - loss: 0.0467 - acc: 0.9855 - val_loss: 0.0322 - val_acc: 0.9890
Epoch 6/12
60000/60000 [==============================] - 7s 115us/step - loss: 0.0428 - acc: 0.9869 - val_loss: 0.0305 - val_acc: 0.9905
Epoch 7/12
60000/60000 [==============================] - 7s 121us/step - loss: 0.0375 - acc: 0.9884 - val_loss: 0.0289 - val_acc: 0.9904
Epoch 8/12
60000/60000 [==============================] - 7s 116us/step - loss: 0.0334 - acc: 0.9893 - val_loss: 0.0303 - val_acc: 0.9894
Epoch 9/12
60000/60000 [==============================] - 7s 118us/step - loss: 0.0307 - acc: 0.9903 - val_loss: 0.0297 - val_acc: 0.9906
Epoch 10/12
60000/60000 [==============================] - 7s 120us/step - loss: 0.0297 - acc: 0.9913 - val_loss: 0.0353 - val_acc: 0.9889
Epoch 11/12
60000/60000 [==============================] - 7s 118us/step - loss: 0.0282 - acc: 0.9911 - val_loss: 0.0301 - val_acc: 0.9915
Epoch 12/12
60000/60000 [==============================] - 7s 118us/step - loss: 0.0262 - acc: 0.9919 - val_loss: 0.0275 - val_acc: 0.9912
Test loss: 0.027537670828175397
Test accuracy: 0.9912

real    1m28.378s
user    1m58.384s
sys     0m21.860s

無事、DockerからKerasでGPUディープラーニングできましたね。
ではでは。

スポンサーリンク