Dockerを使ってpytorch+cudaの環境を構築する

はじめに

研究をやっていると

  • 査読対応のために実験を追加したいが,環境をいじってしまっている
  • 既存手法を実行するために,tensorflowの特定のバージョンを使いたい.それに伴って特定のバージョンのcudaをインストールしなければならない

みたいなことが発生する. pythonだけならcondaやpipenvでなんとかなるが,cudaなどが絡んでくると色々めんどくさくなる.

そこで,Dockerを使って環境を構築することでこの問題を解決することを試みる. もう1台のパソコンや会社のPCで同じことをやるので記録を残す.

cuda+dockerで検索するとnvidia-docker2を使うように書いてある記事がたくさんヒットするが,公式によると,nvidia-docker2はdepercatedでDocker 19.03以降はnvidia-container-toolkitを入れればいいらしい.

環境

家のパソコン

  • Ubuntu18.04
  • GeForce GTX 750 Ti, Core(TM) i7-7700 CPU
  • Docker version 19.03.1, build 74b1e89

gpuが年季入ってる感じなので不安だったけど大丈夫だった.

作りたい環境

  • cuda+pytorchの環境をjupyter notebook上で実行する
  • 作ったファイルはホスト上から参照,編集できるようにする

以下では,ほぼクリーンなubuntuに順番に環境を作っていく.

nvidia-driverのインストール

Dockerを使う場合でも,ホスト側にnvidiaのドライバを入れておく必要がある. 今どきはaptでいれると普通に動いてくれるので良い. ubuntu-driversでrecommendされたバージョンをインストールする.

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
ubuntu-drivers devices

sudo apt install nvidia-driver-430 # recommended

参考:

Dockerのインストール

公式Documentに従ってインストールしていく.

sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt install docker-ce docker-ce-cli containerd.io

sudo docker info

参考:

docker groupの設定

docker groupにuserを追加しておくと,管理者権限なしにdockerを実行できるようになる. dockerグループにはセキュリティ上の問題があると言っている記事もあるので,やらないほうがいいのかもしれないが理解できていないので,あまり検討できてない.

sudo gpasswd -a $USER docker
sudo reboot 

本当はログアウトして再度ログインするだけでいいはずだけど,自分の環境では再起動するまでgroupがうまく変更されていなかった.

docker hubのアカウント作成/ログイン

docker hubには様々なレポジトリが公開されており,これを利用することで誰かが作った色々盛り盛りの環境をさくっと利用することができる. 今回はnvidiaが公開しているものが使いたいので,これに登録,ログインしておく. ログインは以下のようにしてコマンドラインから実行する.

docker login

nvidia-container-toolkit のインストール

cuda+dockerで検索するとnvidia-docker2を使うように書いてある記事がたくさんヒットするが,公式によると,nvidia-docker2はdepercatedでDocker 19.03以降はnvidia-container-toolkitを入れればいいらしい.

最近またdocker2を入れる方法に変わったらしい。なんにせよ公式にその時書かれている手順に従うのが良い

Note that with the release of Docker 19.03, usage of nvidia-docker2 packages are deprecated since NVIDIA GPUs are now natively supported as devices in the Docker runtime.

Documentに従って,nvidia-container-toolkitをインストールする.

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

docker build/run

以下では色々書いているけどnvidiaが公開しているDockerイメージをpullして使うと万事オッケーだと思う nvidiaが公開しているdocker image

ここでは勉強も兼ねて自分でDockerfileを以下のように作る.

FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04

ARG USERNAME

RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install python3
RUN apt-get -y install python3-pip
RUN apt-get -y install nano wget curl

RUN pip3 install jupyter click numpy matplotlib seaborn pandas tqdm
RUN pip3 install torch torchvision

RUN useradd -m -s /bin/bash ${USERNAME}

USER ${USERNAME}

RUN jupyter notebook --generate-config \
 && sed -i.back \
    -e "s:^#c.NotebookApp.token = .*$:c.NotebookApp.token = u'':" \
    -e "s:^#c.NotebookApp.ip = .*$:c.NotebookApp.ip = '0.0.0.0':" \
    -e "s:^#c.NotebookApp.open_browser = .*$:c.NotebookApp.open_browser = False:" \
    /home/${USERNAME}/.jupyter/jupyter_notebook_config.py

WORKDIR /home/${USERNAME}

参考:

これをおいたフォルダで以下のようにしてイメージをビルドする.

docker build ./ --build-arg USERNAME=$USER  -t notebook

ここではbuildの際にホスト側と同じユーザー名のユーザーを作っている. これによって,docker内で作ったファイルが,ホスト側で編集できるようになる. こちらにやると,別のマシンでビルドしたものを使うときにはこれだとだめらしいが,自分のマシンでしか使わないので,これでオッケー -tはイメージの名前なので何でも良い.

RUNしてみて,コンテナからGPUが見えることを確認する.

docker run --gpus all --rm notebook nvidia-smi

f:id:ksknw:20190831211946p:plain

ちゃんと動いていることが確認できた.

次にbashを実行してみる.

  • -itオプションをつけると,docker上でインタラクティブに操作できる.
  • また,-vでホームディレクトリをdocker内のhostディレクトリにマウントしておく.
  • -pはdockerのポートをホストのポートに飛ばすオプションで,jupyterを起動するポートをホストに飛ばしておく. これによって,docker上で起動したjupyterにホスト側からアクセスできるようになる.
docker run --gpus all --rm -v /home/kei:/home/kei/host -p 127.0.0.1:8888:8888 -it notebook bash

あとは普通にjupyter notebookを立ち上げると,いつもと同じようにホスト側のブラウザからlocalhost:8888にアクセスするだけで操作できる. bashを実行しているので,pythonを実行してもよい.

一応動作確認.

f:id:ksknw:20190831215419p:plain

家でやる場合はないけど,リモートサーバーでたてたdocker上のjupyter notebookにアクセスするときは,sshで入るときにポートフォワードすればよい.

参考:

おわりに

  • dockerを使うのはほぼ初めてなので,何か間違っているかもしれない.
  • 毎回--rmをつけてコンテナを使い捨てにするのが再現性的にはいいかなと思っている.
  • nvidia-docker2周りが最近変わったばかりっぽく,nvidia-docker2を入れろと書いてあるブログが多々あって混乱した.
  • これからはプロジェクトごとにDockerfileを作る感じでやっていきたい.

参考