こんにちは。
小説家になろうの作品群を読んでいたら連休が終わりそうです。
連休の終わりのアンミラ帰りに衝撃作TensorFlowでGPUが使えないとそのアンサーエントリであるTensorFlow on DockerでGPUを使えるようにする方法を読み、書いてみたエントリです。先月購入した最低限Maxwell的なグラフィックカード(図1)絡みで見つけたNVIDIA Docker、なかなか良いものなのでもっと多くの方に知ってもらいたいなと思い。
今回はNVIDIA Docker + TensorFlowでGPUを有効活用する手順を紹介します。他の方による関連記事として、日本語でのNVIDIA Docker + Caffe解説はすでにUbuntu14.04.3でnvidia-docker使ってCaffeをインストールしてみたがあります。Caffeな方はそちらを参照ください*1。今回はお題がTensorFlowという点と、NVIDIA公式配布のcuDNN入りイメージを利用する点が異なります。
さらに、NVIDIA Docker用に事前ビルドされたcuDNN入りDockerイメージを利用すると、NVIDIAへの開発者登録無しに(!)cuDNNライブラリを利用できます。
ここでは途中段階でトラブルシュートしやすいように動作確認ステップを多く設けていますが、一旦手順を確立した後は飛ばしても構わないと思います。
実験用に作った環境はこんな感じでした。
今回はUNetbootinで作成したUSBメモリのライブ環境からHDDへインストールしたUbuntu環境を利用しました。
標準グラフィックドライバの都合か、インストール画面の英文字列が歯抜けになって解読に苦労しましたが、普通にデスクトップ版をインストールしました。
OSのインストールが完了して軽く動作確認したらXのターンは終わりです。NVIDIAのドライバはXが走っているとインストールできないので、Xを落とすかGRUBの設定でテキストモードbootさせましょう。そして、デフォルトインストールされるNouveauドライバも邪魔なので無効化しておきます*4。
/etc/default/grubは次のように編集します。
今年こそはUbuntuデスクトップ元年になるでしょうか。このタイミングであわせてOpenSSH Serverをインストールし、以後の作業はSSH経由でおこないます。
としていくつかの質問に答えるだけですんなりドライバのインストールが完了するはずです。
1.9.0以上が必要なので、今回はhttps://docs.docker.com/docker-trusted-registry/cs-engine/install/#install-on-ubuntu-14-04-ltsの手順に従ってインストールしました。
docker infoの結果は次の通りです。
Docker(docker-engine)を正しくインストールできていない場合にはエラーが発生するかもしれません。
正常にインストールできれば、次のようなターミナル出力で終了するはずです。
このあたりで一旦ホストOSを再起動しておきます。
としてみます。
というようにGPUが認識されていれば、ひとまずOKそうです。
アーキテクチャ世代が古かったり、ドライバ競合などによって認識できていなければ、金の弾丸が必要な雰囲気です*5。
https://github.com/NVIDIA/nvidia-docker/blob/master/samples/ubuntu/deviceQuery/Dockerfile
このDockerfileをベースに先頭の行をnvidia/cudaへ書き換えて適当なディレクトリへ保存(私は~/docker/deviceQuery/Dockerfileというパスへ保存しました)し、
でビルドして
と実行すると、
のような結果が出力されるはずです。手元のグラフィックカードによって結果は大きく異なるはずですが、最後にResult = PASSと出ているとなんだか安心しますね。
nbodyなどのサブディレクトリでmakeをおこなえばそれぞれ実行できるので、何か詰まった時には試してみると良いかもしれません。
上記をDockerfile(今回は~/docker/tensorflow/Dockerfileにしました)へ保存して、Dockerfileのあるディレクトリにて
とコマンドを実行するだけです。
ビルド作業の途中でライブラリのビルドが走るため少々時間がかかりますが、成功すれば以下のようにイメージが生えたことを確認できるはずです。
あとは、TensorFlow公式の手順に従って簡単な動作確認をおこないましょう。
動作していますね。
ホスト側で次のコマンドを実行します。
すると次のようにログが延々と出力されます。
実行中に他のターミナルからnvidia-smiを実行してGPUの利用状況を確認してみます。
GPU温度が上がっていますね。ホクホクですね。57度といえばもう少しで大半のタンパク質が変質する温度ですから、長時間稼働すれば半熟玉子ぐらいは作れそうです。
電力をジャブジャブと突っ込んでいるとさすがに個人用PCとしては気になるところですが、計算が終わって1-2分後に再度GPU状況を確認すると
となり、きっちり消費電力も下がっています。安心です。
タグ一覧をざっと見てみると、結構柔軟にさまざまな版を用意してくれていることがわかります(どれだけ動作確認されているかは別問題です)。Ubuntu嫌いの方はCentOSベースのものを利用できます。
latestタグが打たれているデフォルトイメージはUbuntuベースで、pullした結果のサイズは次の通り1.2GB程度です。
扱いやすいですね。
Docker Hub上に標準的な置き方をされているため、派生イメージを作りやすい(実際、今回の手順の途中でTensorFlow入りのものを作ったように)のでとても便利です。
での実行が
のように元気よくInitialized!と叫んであっさり終わってしまう場合、以下のログエントリが出力されていないか確認してみてください。
この場合、cuDNNを含まないDockerイメージを基盤として派生したイメージからコンテナを生成している可能性があります。
イメージ作成用Dockerfileの先頭がFROM nvidia/cudaやFROM nvidia/cuda:latest(あるいはFROM nvidia/cuda:devel)になっている場合、そのイメージにはcuDNNが含まれません。
残念ながら、Dockerfileを修正してTensorFlowを含むDockerイメージをビルドし直する必要があります。この部分を正しくFROM nvidia/cuda:cudnn(またはFROM nvidia/cuda:cudnn-ubuntu14.04など)に変更して再度buildを実施してください。
GPUを利用するプロセスを走らせた状態で/gpu/statusへアクセスすると
と、プロセス情報も出してくれます。至れり尽くせり感がありますね。
これだけあれば情報を定点観測+加工して動作状況として集計、マシン調達や稼働の計画を作るのも楽になるのではないでしょうか。
個人的にはWindows上のdocker-machine+Hyper-V環境のコンテナから楽にGPU利用計算を扱えるととても嬉しいのですが、CUDA Toolkit対NVIDIA GPUドライバの通信仕様がLinux版とWindows版で同じということはさすがにない(=うまくいかない)と思うので試していません。
小説家になろうの作品群を読んでいたら連休が終わりそうです。
連休の終わりのアンミラ帰りに衝撃作TensorFlowでGPUが使えないとそのアンサーエントリであるTensorFlow on DockerでGPUを使えるようにする方法を読み、書いてみたエントリです。先月購入した最低限Maxwell的なグラフィックカード(図1)絡みで見つけたNVIDIA Docker、なかなか良いものなのでもっと多くの方に知ってもらいたいなと思い。
今回はNVIDIA Docker + TensorFlowでGPUを有効活用する手順を紹介します。他の方による関連記事として、日本語でのNVIDIA Docker + Caffe解説はすでにUbuntu14.04.3でnvidia-docker使ってCaffeをインストールしてみたがあります。Caffeな方はそちらを参照ください*1。今回はお題がTensorFlowという点と、NVIDIA公式配布のcuDNN入りイメージを利用する点が異なります。
[*1] このQiitaエントリが書かれたのは2016年1月で、NVIDIA Dockerがイマイチこなれていなかった頃です。当時と今では公式イメージのバリエーションやコマンド利用時の注意点などに若干差異がありますが原則は変わりません。
NVIDIA Dockerの概要
NVIDIA Dockerは、NVIDIAが開発しているDockerプラグインです。Dockerホスト側にNVIDIA GPUドライバを持たせ、Dockerコンテナ側にCUDA Toolkit(+cuDNN)を持たせるという明確な役割分担により、同一ホスト上の複数コンテナでバージョンの異なるCUDA Toolkitを柔軟に組み合わせられます。さらに、NVIDIA Docker用に事前ビルドされたcuDNN入りDockerイメージを利用すると、NVIDIAへの開発者登録無しに(!)cuDNNライブラリを利用できます。
NVIDIA Docker利用のメリット
- ホストとコンテナでCUDA Toolkitのバージョンを揃える必要がなくなる
- 何よりもこれです。コンテナ間で異なるCUDA Toolkitバージョン(たとえば7.0と7.5)を利用したい場合に悩む必要がなくなります。
- CUDA Toolkit 6.5系で開発して7.5系へ上げたくない、というコンテナが「古いバージョンにひきこもり続け」られるようになります。
- 導入が比較的簡単
- 通常のNVIDIA GPUドライバをインストールした通常のDocker環境にプラグインひとつインストールするだけなので、手軽です。
- EULAにまつわる厄介事を回避できる(かもしれない)
- ドライバや各種ツールキットのEULAというのは、なかなか厄介なものです。最近もDockerコンテナ上でのJavaの実行はライセンス違反なのか?あたりが話題になっていました。
- 個人的にはDocker Hubから入手できるイメージの利用に関するライセンス同意に改善の余地があると思いますが、なにぶんNVIDIA Docker向け公式イメージはNVIDIA本家がメンテナンスしているものです。Docker Hub上のプロジェクトページにEULAの記載がないことは少々不安ですが、公式配布している以上は最低限の実行+ローカル派生イメージ作成あたりで文句をいわれることはないでしょう(多分*2)
[*2] その派生イメージをDocker Hubへ突っ込んで良いかどうかは別問題かと思いますので、ここでは議論しません。issueを立てて開発チームへ確認すべき案件でしょう。
NVIDIA Docker利用のデメリット
- まだ利用者があまり多くないので枯れていない
- 現状(2016/05/08)、1.0.0-rc状態*3で、そろそろ基本的なところでつまづくことはなくなってきたようには思いますが、利用者が何万人もいる状況ではありません。
- 簡単なテスト動作をおこなううえでは問題ありませんが、ちょっと実用的で凝ったことをやろうと思うと謎のエラーと戦ったりGitHubのissuesとにらめっこすることになるかもしれません。
- 通常のDockerとNVIDIA Dockerを混ぜて利用する手順の確立に工夫が必要
- docker-machineやcompose、swarmを利用して大規模環境を構築する際にはラベルフィルタなどをうまく使って非GPUホストへGPU利用前提のコンテナをデプロイしないなどの制約掛けが必要となるはずです(未検証)。
- もちろん、この部分の厄介さは非NVIDIA Docker環境(通常のDockerを使ってディレクトリ共有・デバイス共有でCUDA/cuDNNを利用するパターン)でも変わりません。
[*3] 個人的には、cuDNN 5のRCが取れて正式リリースされるタイミングでNVIDIA Dockerも1.0.0正式版をリリースするのだろうと踏んでいます。
導入手順の概略
NVIDIAの一定以上新しいドライバを正しくインストールできたUbuntu環境があれば、10分とかからずに動作確認できるでしょう。ここでは途中段階でトラブルシュートしやすいように動作確認ステップを多く設けていますが、一旦手順を確立した後は飛ばしても構わないと思います。
- 生のUbuntu 14.04環境(Dockerホスト)を用意する
- Dockerホスト側へNVIDIA GPUの最新ドライバをインストールする
- Dockerホスト側へDocker(docker-engine)とNVIDIA Dockerをインストールし、動作確認をする
- cuDNN入りイメージをベースにTensorFlow込みのイメージ(カスタムイメージ)を作成する
- カスタムイメージから生成したコンテナでGPUを利用できることを確認する
- MNISTでTensorFlow+GPU(cuDNN)の動作確認
実験用に作った環境はこんな感じでした。
環境
- グラフィックカード: GeForce GTX 750Ti
- NVIDIAドライバ: 361.42
- OS: Ubuntu 14.04.4 LTS
- Docker engine: 1.10.3-cs3
- NVIDIA Dockerコンテナ
- CUDA: 7.5
- cuDNN: 4(4.0.7)
- TensorFlow: 0.8.0(GPU版)
- Python: 2.7.6
生のUbuntu 14.04環境(Dockerホスト)を用意する
Ubuntu 14.04のインストールです。今回はUNetbootinで作成したUSBメモリのライブ環境からHDDへインストールしたUbuntu環境を利用しました。
標準グラフィックドライバの都合か、インストール画面の英文字列が歯抜けになって解読に苦労しましたが、普通にデスクトップ版をインストールしました。
OSのインストールが完了して軽く動作確認したらXのターンは終わりです。NVIDIAのドライバはXが走っているとインストールできないので、Xを落とすかGRUBの設定でテキストモードbootさせましょう。そして、デフォルトインストールされるNouveauドライバも邪魔なので無効化しておきます*4。
/etc/default/grubは次のように編集します。
GRUB_CMDLINE_LINUX_DEFAULT="text nouveau.modeset=0"
[*4] Nouveauドライバの無効化についてはAutodeskのヘルプページが分かりやすいので、困ったら参照してください。
Dockerホスト側へNVIDIAの最新ドライバをインストールする
前段階できちんとNouveauドライバを無効化しておけば、$ sudo ./NVIDIA-Linux-x86_64-361.42.run
Dockerホスト側へDocker(docker-engine)とNVIDIA Dockerをインストールし、動作確認をする
Docker(docker-engine)をインストールする
NVIDIA DockerはDocker(docker-engine)のプラグインとして構築されているので、まずDocker本体をインストールする必要があります。1.9.0以上が必要なので、今回はhttps://docs.docker.com/docker-trusted-registry/cs-engine/install/#install-on-ubuntu-14-04-ltsの手順に従ってインストールしました。
docker infoの結果は次の通りです。
$ docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 1.10.3-cs3 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 0 Dirperm1 Supported: true Execution Driver: native-0.2 Logging Driver: json-file Plugins: Volume: local Network: bridge null host Kernel Version: 4.2.0-27-generic Operating System: Ubuntu 14.04.4 LTS OSType: linux Architecture: x86_64 CPUs: 4 Total Memory: 7.734 GiB Name: muo-desktop ID: 7MD3:N656:PHZ6:LROY:ML3K:J4OF:4RGW:YRV4:HCCK:YQI4:ZMSZ:SI5I WARNING: No swap limit support
NVIDIA Dockerをインストールする
公式の手順通り次のコマンドにてインストールします。$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0-rc/nvidia-docker_1.0.0.rc-1_amd64.deb $ sudo dpkg -i /tmp/nvidia-docker_1.0.0.rc-1_amd64.deb && rm /tmp/nvidia-docker*.deb
正常にインストールできれば、次のようなターミナル出力で終了するはずです。
Preparing to unpack .../nvidia-docker_1.0.0.rc-1_amd64.deb ... nvidia-docker stop/waiting Unpacking nvidia-docker (1.0.0~rc-1) over (1.0.0~rc-1) ... nvidia-docker (1.0.0~rc-1) を設定しています ... Adding system user `nvidia-docker' (UID 117) ... Adding new user `nvidia-docker' (UID 117) with group `nogroup' ... Not creating home directory `/var/lib/nvidia-docker'. nvidia-docker start/running, process 18051 Processing triggers for ureadahead (0.100.0-16) ... muo@muo-desktop:~$
NVIDIA Dockerの簡単な動作確認をおこなう
これまた公式の手順通り$ nvidia-docker run --rm nvidia/cuda nvidia-smi
$ nvidia-docker run --rm nvidia/cuda nvidia-smi Sun May 8 07:00:24 2016 +------------------------------------------------------+ | NVIDIA-SMI 361.42 Driver Version: 361.42 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 750 Ti Off | 0000:01:00.0 Off | N/A | | 22% 33C P8 1W / 38W | 7MiB / 2046MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
アーキテクチャ世代が古かったり、ドライバ競合などによって認識できていなければ、金の弾丸が必要な雰囲気です*5。
さらにいくつかCUDA関連の動作確認をおこなう
deviceQueryの動作確認
NVIDIA Dockerリポジトリには、NVIDIA DockerがサポートするGPUデバイスを検出するサンプルがあります。https://github.com/NVIDIA/nvidia-docker/blob/master/samples/ubuntu/deviceQuery/Dockerfile
このDockerfileをベースに先頭の行をnvidia/cudaへ書き換えて適当なディレクトリへ保存(私は~/docker/deviceQuery/Dockerfileというパスへ保存しました)し、
$ nvidia-docker build -t local:deviceQuery .
$ nvidia-docker run --rm local:deviceQuery
./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "GeForce GTX 750 Ti" CUDA Driver Version / Runtime Version 8.0 / 7.5 CUDA Capability Major/Minor version number: 5.0 Total amount of global memory: 2047 MBytes (2145927168 bytes) ( 5) Multiprocessors, (128) CUDA Cores/MP: 640 CUDA Cores GPU Max Clock rate: 1084 MHz (1.08 GHz) Memory Clock rate: 2700 Mhz Memory Bus Width: 128-bit L2 Cache Size: 2097152 bytes Maximum Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096) Maximum Layered 1D Texture Size, (num) layers 1D=(16384), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(16384, 16384), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 1 copy engine(s) Run time limit on kernels: No Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Device PCI Domain ID / Bus ID / location ID: 0 / 1 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 8.0, CUDA Runtime Version = 7.5, NumDevs = 1, Device0 = GeForce GTX 750 Ti Result = PASS
その他のサンプル動作確認
実は、前述のdeviceQueryで作成したイメージにはCUDAのサンプルが一式含まれます。nbodyなどのサブディレクトリでmakeをおこなえばそれぞれ実行できるので、何か詰まった時には試してみると良いかもしれません。
[*5] NVIDIA DockerリポジトリのwikiにCUDA Toolkitバージョンごとの最低ドライババージョンとGPUアーキテクチャが記載されているので、参考にしてください。
cuDNN入りイメージをベースにTensorFlow込みのイメージ(カスタムイメージ)を作成する
お待ちかねの本編というところですが、とても簡単です。FROM nvidia/cuda:cudnn RUN apt-get update \ && apt-get install -y --no-install-recommends python-pip python-dev \ && pip install --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.8.0-cp27-none-linux_x86_64.whl \ && rm -rf /var/lib/apt/lists/*
$ nvidia-docker build -t local:tf .
ビルド作業の途中でライブラリのビルドが走るため少々時間がかかりますが、成功すれば以下のようにイメージが生えたことを確認できるはずです。
$ nvidia-docker images REPOSITORY TAG IMAGE ID CREATED SIZE local tf 7461583755dd 4 minutes ago 1.707 GB local nbody c7559dcc54c7 21 minutes ago 1.467 GB local deviceQuery 3bab450c41f8 29 minutes ago 1.464 GB nvidia/cuda cudnn baffdac82a9d 4 days ago 1.354 GB nvidia/cuda latest 981203204dd5 4 days ago 1.229 GB
$ nvidia-docker run --rm -it local:tf /bin/bash
# python ... >>> import tensorflow as tf I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcublas.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcudnn.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcufft.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcuda.so.1 locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcurand.so locally
>>> sess = tf.Session() I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:900] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero I tensorflow/core/common_runtime/gpu/gpu_init.cc:102] Found device 0 with properties: name: GeForce GTX 750 Ti major: 5 minor: 0 memoryClockRate (GHz) 1.0845 pciBusID 0000:01:00.0 Total memory: 2.00GiB Free memory: 1.96GiB I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0: Y I tensorflow/core/common_runtime/gpu/gpu_device.cc:755] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 750 Ti, pci bus id: 0000:01:00.0)
>>> a = tf.constant(10) >>> b = tf.constant(32) >>> print(sess.run(a + b)) 42 >>>
カスタムイメージから生成したコンテナでGPUを利用できることを確認する
MNISTでTensorFlow+GPU(cuDNN)の動作確認
ここでは、定番のMNISTを利用して正しくGPUを利用できていることを確認します。ホスト側で次のコマンドを実行します。
$ nvidia-docker run --rm local:tf python -m tensorflow.models.image.mnist.convolutional
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcublas.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcudnn.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcufft.so locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcuda.so.1 locally I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcurand.so locally Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes. Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes. Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes. Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes. Extracting data/train-images-idx3-ubyte.gz Extracting data/train-labels-idx1-ubyte.gz Extracting data/t10k-images-idx3-ubyte.gz Extracting data/t10k-labels-idx1-ubyte.gz I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:900] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero I tensorflow/core/common_runtime/gpu/gpu_init.cc:102] Found device 0 with properties: name: GeForce GTX 750 Ti major: 5 minor: 0 memoryClockRate (GHz) 1.0845 pciBusID 0000:01:00.0 Total memory: 2.00GiB Free memory: 1.96GiB I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0: Y I tensorflow/core/common_runtime/gpu/gpu_device.cc:755] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 750 Ti, pci bus id: 0000:01:00.0) Initialized! Step 0 (epoch 0.00), 577.0 ms Minibatch loss: 12.054, learning rate: 0.010000 Minibatch error: 90.6% Validation error: 84.6% Step 100 (epoch 0.12), 15.3 ms Minibatch loss: 3.294, learning rate: 0.010000 Minibatch error: 4.7% Validation error: 7.3% Step 200 (epoch 0.23), 15.1 ms Minibatch loss: 3.470, learning rate: 0.010000 Minibatch error: 10.9% Validation error: 4.0% ... 以下略
$ nvidia-docker run --rm nvidia/cuda nvidia-smi Sun May 8 08:07:38 2016 +------------------------------------------------------+ | NVIDIA-SMI 361.42 Driver Version: 361.42 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 750 Ti Off | 0000:01:00.0 Off | N/A | | 36% 57C P0 30W / 38W | 1926MiB / 2046MiB | 80% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| +-----------------------------------------------------------------------------+
電力をジャブジャブと突っ込んでいるとさすがに個人用PCとしては気になるところですが、計算が終わって1-2分後に再度GPU状況を確認すると
$ nvidia-docker run --rm nvidia/cuda nvidia-smi Sun May 8 08:11:27 2016 +------------------------------------------------------+ | NVIDIA-SMI 361.42 Driver Version: 361.42 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 750 Ti Off | 0000:01:00.0 Off | N/A | | 27% 35C P8 1W / 38W | 7MiB / 2046MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
その他
Dockerイメージとそのバリエーションについて
nvidia-dockerコマンドでは特殊なDockerレジストリからイメージを拾ってくるかとおもいきや、普通にDocker Hub上のnvidia/cudaからイメージを拾ってくるという素直な作りです。タグ一覧をざっと見てみると、結構柔軟にさまざまな版を用意してくれていることがわかります(どれだけ動作確認されているかは別問題です)。Ubuntu嫌いの方はCentOSベースのものを利用できます。
latestタグが打たれているデフォルトイメージはUbuntuベースで、pullした結果のサイズは次の通り1.2GB程度です。
muo@muo-desktop:~$ nvidia-docker images REPOSITORY TAG IMAGE ID CREATED SIZE nvidia/cuda latest 981203204dd5 4 days ago 1.229 GB
Docker Hub上に標準的な置き方をされているため、派生イメージを作りやすい(実際、今回の手順の途中でTensorFlow入りのものを作ったように)のでとても便利です。
トラブルシューティング: MNISTの動作が途中で終了してしまう場合
$ nvidia-docker run --rm local:tf python -m tensorflow.models.image.mnist.convolutional
... Extracting data/train-images-idx3-ubyte.gz Extracting data/train-labels-idx1-ubyte.gz Extracting data/t10k-images-idx3-ubyte.gz Extracting data/t10k-labels-idx1-ubyte.gz Initialized!
I tensorflow/stream_executor/dso_loader.cc:99] Couldn't open CUDA library libcudnn.so. LD_LIBRARY_PATH: /usr/local/nvidia/lib:/usr/local/nvidia/lib64: I tensorflow/stream_executor/cuda/cuda_dnn.cc:1562] Unable to load cuDNN DSO
イメージ作成用Dockerfileの先頭がFROM nvidia/cudaやFROM nvidia/cuda:latest(あるいはFROM nvidia/cuda:devel)になっている場合、そのイメージにはcuDNNが含まれません。
残念ながら、Dockerfileを修正してTensorFlowを含むDockerイメージをビルドし直する必要があります。この部分を正しくFROM nvidia/cuda:cudnn(またはFROM nvidia/cuda:cudnn-ubuntu14.04など)に変更して再度buildを実施してください。
公式Dockerイメージに含まれるcuDNNのバージョン
現状、公式のcudnnイメージに含まれるcuDNNのバージョンは4系(4.0.7)を正式として3系も別タグで提供されています。現在(2016/05/08時点)、cuDNN 5のRC版がリリースされていますが、このイメージは提供されていません。この点について、NVIDIAのチームメンバーがcuDNN 5のRCが取れて正式リリースされたらイメージも更新すると表明しています。GPUステータス情報へのWebからのアクセス
NVIDIA Dockerでは、HTTP経由でdiag情報へアクセスできます。$ curl http://localhost:3476/gpu/info Driver version: 361.42 Supported CUDA version: 8.0 Device #0 Model: GeForce GTX 750 Ti UUID: GPU-9e723e86-d279-8a3d-25a4-010ecfa20551 Path: /dev/nvidia0 Family: Maxwell Arch: 5.0 Cores: 640 Power: 38 W CPU Affinity: NUMA node0 PCI Bus ID: 0000:01:00.0 BAR1: 256 MiB Bandwidth: 15760 MB/s Memory ECC: false Global: 2046 MiB Constant: 64 KiB Shared: 64 KiB L2 Cache: 2048 KiB Bandwidth: 86400 MB/s Clocks Cores: 1293 MHz Memory: 2700 MHz P2P Available: None $ curl http://localhost:3476/gpu/status Device #0 Power: 1 / 38 W Temperature: 33 °C Utilization GPU: 0 % Memory: 1 % Encoder: 0 % Decoder: 0 % Memory Global: 7 / 2046 MiB ECC Errors L1 Cache: N/A L2 Cache: N/A Global: N/A PCI BAR1: 1 / 256 MiB Throughput RX: 0 MB/s TX: 0 MB/s Clocks Cores: 135 MHz Memory: 405 MHz Processes: None
... Clocks Cores: 1019 MHz Memory: 2700 MHz Processes - PID: 16759 Name: python Memory: 1841 MiB
これだけあれば情報を定点観測+加工して動作状況として集計、マシン調達や稼働の計画を作るのも楽になるのではないでしょうか。
docker-compose + docker-machine ?
おそらく、単純な実験を超えた実用の際にはdocker-machine+docker-compose(そしてswarm)を利用するでしょう。その場合はhttps://github.com/NVIDIA/nvidia-docker/issues/8を参照することになると思いますが、手元では今回試していません。まとめ
NVIDIA Dockerを使ってcuDNN+TensorFlow環境を作る手順は割とシンプルです。先人がハマりにハマって踏み固められた道という感じで、今回の手順中で特段ハマる箇所はありませんでした。個人的にはWindows上のdocker-machine+Hyper-V環境のコンテナから楽にGPU利用計算を扱えるととても嬉しいのですが、CUDA Toolkit対NVIDIA GPUドライバの通信仕様がLinux版とWindows版で同じということはさすがにない(=うまくいかない)と思うので試していません。