前書き
このドキュメントはhttp://geotaru.hatenablog.com/entry/2018/07/06/153208 の改正版です。
20180803現在、Ubuntu 18.04ではCUDA9.1をインストールできますが、下記リンクによるとTensorFlowの最新版はCUDA 9.0に対応しています。Ubuntu18.04にCUDA 9.0を入れるのはなんだかめんどくさそう...
TensorFlowのアップデートを待とうと考えていますが、Dockerを使って楽に環境構築する方法を確立したので共有します。Dockerのオーバヘッドが小さいなら、環境が汚れないからこの方法を維持するのがいいのではないでしょうか?
Keras on TensorFlow with GPUを使えるようにする
Overview
手順を簡単に説明すると
- NVIDIA DriverをホストマシンのUbuntu 18.04にインストール
- Dockerをインストール
- NVIDIA Dockerをインストール
- GitHubまたはBitbucketのリポジトリにDockerfileを置く
- DockerHubと上のリポジトリを連携させる(Automated Build)
- Dockerfileからイメージをダウンロードして起動
Pros/Cons
利点
* 安定したバージョンのCUDAを使える
* 環境を持ち運べる
* CUDAやcudnnをホストマシンにインストールする手間が省ける
欠点
- Dockerによるオーバーヘッドの発生
Requirements
- Docker 18.06.0-ce
- NVIDIA Docker
- Ubuntu 18.04
- NVIDIA Driver 390.48, 390.77で動作確認済み
- ネットワーク環境: Proxyの影響下の環境であればProxyの設定をホストマシンにしてください
NVIDIA DriverはUbuntu 18.04なら
$ sudo ubuntu-drivers autoinstall
で簡単にインストールできます
Dockerグループにユーザを追加
Dockerをsudoなしで使うためのコマンドを実行
しなくても良いがすると楽。
$ sudo gpasswd -a $USER docker
Quick Start
下記のようなシェルスクリプトを書いて実行!
実行するとJupyter Notebookが動いているインスタンスが生成されます。
#!/bin/bash
docker run --runtime=nvidia \
-e NVIDIA_VISIBLE_DEVICES=0 \
--rm \
-p 60000:8888 \
-v `pwd`:/notebooks \
-v /home/geotaru/data/:/notebooks/data \
-it \
geotaru/keras-notebook
tokenをコピーしてブラウザを開き、
"GPUサーバのURL":60000/?token="上のコマンドを実行して表示されたtoken"
にアクセスすれば親の顔より見たJupyter Notebookが!!
上のシェルスクリプトの説明
若干の語弊があるかもしれないですが、だいたいコメントのような意味です。
#!/bin/bash
docker run --runtime=nvidia \ # NVIDIAのドライバを使用する
-e NVIDIA_VISIBLE_DEVICES=0 \ # GPUのID "0,1"とやるとGPUを2本使える(GPUが2本あれば)
--rm \ # Dockerのインスタンスをstop時に消す
-p 60000:8888 \ # ホストの60000ポートとDockerの8888ポートを繋ぐ
-v `pwd`:/notebooks \ # カレントディレクトリをDockerの中の/notebooksディレクトリとする
-v /home/geotaru/data/:/notebooks/data \ # 上と同様に
-it \ # コマンドラインをインタラクティブにする
geotaru/keras-notebook # DockerHubのリポジトリ geotaru/keras-notebookのイメージを使用
Dockerfile
私のDocker imageを使用してもいいですが、自分でカスタマイズしたくなるでしょう。
Dockerfileを書き換えればキーバインドをEmacsにしたりすることもできる上に、好きなライブラリを入れることもできます。
まず、GitHubまたはBitbucketにリポジトリを作成してそこに下記のようなDockerfileを置きます。
FROM nvidia/cuda:9.0-cudnn7-devel-ubuntu16.04
MAINTAINER geotaru
# 一部のライブラリをインストールするときに
# スクリプトが止まらないように下記の環境変数を設定する
ENV DEBIAN_FRONTEND=noninteractive
# Pythonをソースからコンパイルするのに必要なライブラリをインストール
RUN apt-get update -y && apt-get upgrade -y && \
apt-get install -y git \
build-essential \
graphviz \
make \
build-essential \
libssl-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
wget \
curl \
llvm \
libncurses5-dev \
libncursesw5-dev \
xz-utils \
tk-dev \
libffi-dev
# Python
WORKDIR /opt
RUN wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz && \
tar xf Python-3.6.6.tgz
WORKDIR /opt/Python-3.6.6
RUN ./configure && \
make && \
make install && \
rm /opt/Python-3.6.6.tgz
# 欲しいライブラリをインストール
RUN pip3 install --upgrade pip && \
pip3 install numpy \
scipy \
pandas \
h5py \
scikit-learn \
imbalanced-learn \
nose \
xgboost \
lightgbm \
tensorflow-gpu \
keras \
seaborn \
matplotlib \
plotly \
jupyter \
tqdm \
cython \
jupyter_contrib_nbextensions \
pydot \
graphviz \
pydot3 \
pydot-ng \
folium \
autopep8 \
line_profiler \
memory_profiler \
rise
# Jupyter NotebookのExtensionの設定
RUN jupyter contrib nbextension install --user && \
: "Jupyter NotebookのキーバインドをVim風に設定" && \
mkdir -p $(jupyter --data-dir)/nbextensions && \
cd $(jupyter --data-dir)/nbextensions && \
git clone https://github.com/lambdalisue/jupyter-vim-binding vim_binding && \
jupyter nbextension enable vim_binding/vim_binding && \
: "Jupyter Notebookでプレゼンをするためのライブラリ" && \
jupyter-nbextension install rise --py --sys-prefix && \
jupyter-nbextension enable rise --py --sys-prefix && \
: "セルごとに実行時間を測定" && \
jupyter-nbextension enable execute_time/ExecuteTime && \
jupyter nbextension enable move_selected_cells/main && \
jupyter nbextension enable toggle_all_line_numbers/main && \
jupyter nbextension enable code_prettify/code_prettify && \
jupyter nbextension enable scratchpad/main
WORKDIR /notebooks
EXPOSE 8888
ENTRYPOINT ["jupyter", "notebook", "--no-browser", "--ip=0.0.0.0", "--allow-root"]
このDockerfileの問題点
-
バージョン固定
pip install hogeのところは本当はバージョン固定した方がよいとおもいます。面倒なのでここではやっていませんが。 -
Dockerイメージが大きいのでビルドにしか使用していないライブラリは削除したい...
DockerHubを利用する
Proxyの影響下の環境ではProxyの設定が必要で面倒なので(コンテナの中からも通信できるように設定する必要がある)、DockerHub上でビルドすると楽でしょう。Proxyの影響下ではなくても、ビルドが楽になるのでおすすめです。
DockerHubのアカウントを作成して、ホーム画面の右上 create -> Create Automated Buildでさっき作成したリポジトリを指定してください。
詳しくはDocker docsを参照してください。
ビルドには時間がかかります。
うまく設定できれば、GitHubやGitBucketのリポジトリが更新されるたびに自動でDockerHub上でDocker imageがビルドされるようになります。
DockerHubをどうしても使用したくないなら、家などProxyのない場所でDocker imageをビルドしてハードディスクに入れて持って来るとか、scpで持って来るとかすれば良いでしょう。
ビルドできたら...
$ docker pull "DockerHubアカウント名"/"リポジトリ名"
で自分が作ったイメージをダウンロードできる。
最初に書いたようなスクリプトを書いて実行してください。
#!/bin/bash
docker run --runtime=nvidia \
-e NVIDIA_VISIBLE_DEVICES=0 \
--rm \
-p 60000:8888 \
-v `pwd`:/notebooks \
-v /home/geotaru/data/:/notebooks/data \
-it \
geotaru/keras-notebook
geotaru@gpu-server:~/project/interactive$ chmod +x ./run.sh # 実行権限の付与
geotaru@gpu-server:~/project/interactive$ ./run.sh
[I 22:24:12.442 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
[I 22:24:12.568 NotebookApp] [jupyter_nbextensions_configurator] enabled 0.4.0
[I 22:24:12.568 NotebookApp] Serving notebooks from local directory: /notebooks
[I 22:24:12.568 NotebookApp] The Jupyter Notebook is running at:
[I 22:24:12.568 NotebookApp] http://(f11eb68ebfa1 or 127.0.0.1):8888/?token=01bdb4d77d7f893f35423007968035149360374a6d30e48d
[I 22:24:12.568 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 22:24:12.568 NotebookApp]
Copy/paste this URL into your browser when you connect for the first time,
to login with a token:
http://(f11eb68ebfa1 or 127.0.0.1):8888/?token=01bdb4d77d7f893f35423007912345649362361b6d30e48d
tokenをコピーしてブラウザを開き、
"GPUサーバのURL":60000/?token=01bdb4d77d7f893f35423007912345649362361b6d30e48d
をURL欄に書いてアクセスするとJupyter Notebookの画面がでます!
まとめ
NVIDIA DockerとDocker Hubを活用して、Proxy環境下であろうと機械学習の環境構築を簡単にできるようにした。
おまけ
稼動中のDockerのインスタンスを止める方法
$ docker ps -a # どんなインスタンスがあるか確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f9bf6bfc6e68 geotaru/keras-notebook "jupyter notebook --…" 10 seconds ago Up 7 seconds 0.0.0.0:60000->8888/tcp ecstatic_meninsky
上記のインスタンスは--rmオプションで実行しているため、stopするだけでDockerインスタンスが停止し削除される。
$ docker stop ecstatic_meninsky
ecstatic_meninsky
$ docker ps -a # インスタンスがなくなったことを確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
既存のDocker imageを削除する方法
$ docker ps -a
で削除したいイメージのインスタンス確認する。
使っているものがあったら、
$ docker stop "インスタンス名"
$ docker rm "インスタンス名"
とする。
削除したいイメージのインスタンスがなければ
$ docker rmi "イメージの名前"
で破棄できる