はじめに
「Jetson NanoでDockerを動かす(実践編)」ではDockerコンテナ内でGPUが動いているようで動いていなかった。その原因を調査し解決したのでここにまとめる。
問題点のおさらい
Dockerコンテナ内でTensorFlowを動かした際に、CUDAが利用可能なデバイスが見つからないと表示された。
failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
調べたところ、先の例ではGPUは正しく動いていなかったことが判明した。そのため調査は難航するかに思えた。
原因調査
/proc原因説
最初に/procを見ていない可能性を調べた。というのもエラーログ内に/proc/driver/nvidia/version does not exist
という表示があったためだ。当然そのようなファイルはなかったが、ホスト側にも同じように存在しなかった。ということは無くても動作するものである。
yamamo-to@jetson-nano:~$ ls /proc/driver/
rtc
サンプルプログラムによる問題点の切り分け
次にTensorFlowではなく/usr/local/cuda-10.0/samples/
にあるサンプルをいくつか試すことにした。これらはCUDAを直接呼び出しているため問題点の切り分けに使えると考えたからだ。結果、どれも動作しなかった。ということは、前回動いたと考えていたTensorFlowはCPUで動いておりGPUでは動作していなかった可能性が高い。
foo@0e51fe8e73fc:~/samples/0_Simple/simplePrintf$ ./simplePrintf
CUDA error at ../../common/inc/helper_cuda.h:708 code=38(cudaErrorNoDevice) "cudaGetDeviceCount(&device_count)"
パーミッション
結果としてはパーミッションが原因だった。
今回用意したDockerコンテナは、ビルド時に一般ユーザfooを作成しコンテナ実行時にはそのユーザ権限でコマンドを実行する。それを止めて一時的にroot権限に変更したところあっさりとGPUを認識した。ということはパーミッションが足りていないのか?と思い調べたところ
crw-rw---- 1 root video 506, 1 6月 13 19:17 /dev/nvhost-as-gpu
crw-rw---- 1 root video 242, 0 6月 13 19:17 /dev/nvhost-ctrl
crw-rw---- 1 root video 506, 2 6月 13 19:17 /dev/nvhost-ctrl-gpu
crw-rw---- 1 root video 242, 26 6月 13 19:17 /dev/nvhost-ctrl-isp
crw-rw---- 1 root video 242, 30 6月 13 19:17 /dev/nvhost-ctrl-isp.1
crw-rw---- 1 root video 242, 10 6月 13 19:17 /dev/nvhost-ctrl-nvdec
crw-rw---- 1 root video 242, 34 6月 13 19:17 /dev/nvhost-ctrl-vi
crw-rw---- 1 root video 506, 6 6月 13 19:17 /dev/nvhost-ctxsw-gpu
crw-rw---- 1 root root 506, 3 6月 13 19:17 /dev/nvhost-dbg-gpu
crw-rw---- 1 root video 506, 0 6月 13 19:17 /dev/nvhost-gpu
crw-rw---- 1 root video 242, 25 6月 13 19:17 /dev/nvhost-isp
crw-rw---- 1 root video 242, 29 6月 13 19:17 /dev/nvhost-isp.1
crw-rw---- 1 root video 242, 17 6月 13 19:17 /dev/nvhost-msenc
crw-rw---- 1 root video 242, 9 6月 13 19:17 /dev/nvhost-nvdec
crw-rw---- 1 root video 242, 21 6月 13 19:17 /dev/nvhost-nvjpg
crw-rw---- 1 root root 506, 4 6月 13 19:17 /dev/nvhost-prof-gpu
crw-rw---- 1 root video 506, 7 6月 13 19:17 /dev/nvhost-sched-gpu
crw-rw---- 1 root video 242, 1 6月 13 19:17 /dev/nvhost-tsec
crw-rw---- 1 root video 242, 5 6月 13 19:17 /dev/nvhost-tsecb
crw-rw---- 1 root video 506, 5 6月 13 19:17 /dev/nvhost-tsg-gpu
crw-rw---- 1 root video 242, 33 6月 13 19:17 /dev/nvhost-vi
crw-rw---- 1 root video 242, 13 6月 13 19:17 /dev/nvhost-vic
crw-rw---- 1 root video 10, 61 6月 13 19:17 /dev/nvmap
所有者はrootだがグループパーミッションに「read」「write」権限がそれぞれ付与されていた。そしてグループは多くがvideo
だった。Dockerコンテナではないホスト側の一般ユーザyamamo-to
はvideo
グループに所属するのかと確認したところ、
$ grep video /etc/group
video:x:44:yamamo-to,gdm
ビンゴ!
パーミッション修正後
Dockerコンテナをビルド時に一般ユーザfoo
をvideo
グループに所属させるように変更した。
その結果、見事にGPUを伴って動作するようになった。
最後に
無事にDockerを起動できるようになったが調査の途中で/dev/nv*のデバイスファイルを破壊してしまった。これはDocker内をroot権限で起動した際に何かの拍子でファイルが削除されてしまったためである。そのためコンテナ起動時に--device
オプションでコンテナに渡すデバイスは調べた上で最小限にした(githubは既にそのように更新)。
ホスト環境をなるべく破壊しないためのDockerだが、Dockerに/dev以下を壊されてしまっては元も子もないので、Dockerを用いるときは十分気をつけた上で実行した方が良いと考える今日この頃である。