Nvidia Dockerを用いてDockerコンテナからGPUを利用する
ディープラーニング系の処理でもDockerを使いたい!ということで、Nvidia Dockerを利用してDockerコンテナでGPUを使ってみました。 マシンはAWSのp2.xlargeインスタンス(NVIDIA K80を積んでいます)を、OSはUbuntu 18.04を利用しました。
Dockerのインストール・設定
まずはDockerをインストールします。
インストール
バージョンは1.12以降である必要があります。
Dockerの公式ドキュメント を参考にしています。
$ sudo apt-get update $ sudo apt-get 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-get update $ sudo apt-get install docker-ce docker-ce-cli containerd.io
確認
実際に入ったか確かめます。Hello from Docker!
みたいなのが表示されれば成功です。
$ sudo docker run hello-world
権限周りの設定
rootでdockerコマンドを毎回実行するのもあれなので、設定します。
docker
グループに現在のユーザーを追加します。
$ sudo usermod -aG docker $USER
再ログインすると、sudoなしでdockerコマンドを実行できるようになります。
Nvidia CUDA Toolkitのインストール
Nvidia Dockerをインストールするために必要なCUDA Toolkitをインストールします。 Nvidiaの公式ドキュメントが参考になります。
準備
gccやmakeなどもろもろが必要になるので、インストールします。
$ sudo apt-get install build-essential
インストール
インストーラをダウンロードします。
$ wget https://developer.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.105_418.39_linux.run
こちらを参考にハッシュ値を確認します。
$ md5sum cuda_10.1.105_418.39_linux.run
インストーラを実行します。
$ sudo sh cuda_10.1.105_418.39_linux.run
途中で、規約への同意が求められます。また、その後何をインストールしたいのか聞かれますが全部選択しても大丈夫だと思います。
確認
インストールが終了したら、以下のコマンドを実行してみます。現在のGPUの状態などが表示されたら成功です。
$ nvidia-smi
Nvidia Dockerのインストール
以下のようなコマンドでNvidia Dockerをインストールします。これで終わりです。
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ sudo apt-key add - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ 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-docker2 $ sudo pkill -SIGHUP dockerd
実際に使ってみる
TensorFlowの公式ドキュメントにあった、GPUを用いた計算の例をを実行してみます。2次元のテンソルの要素の和を求めています。
$ docker run --runtime=nvidia -it --rm tensorflow/tensorflow:latest-gpu \ python -c "import tensorflow as tf; tf.enable_eager_execution(); print(tf.reduce_sum(tf.random_normal([1000, 1000])))" 2019-02-28 00:15:38.920366: 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-02-28 00:15:41.032922: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:998] 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-02-28 00:15:41.033785: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x3f815f0 executing computations on platform CUDA. Devices: 2019-02-28 00:15:41.033815: I tensorflow/compiler/xla/service/service.cc:158] StreamExecutor device (0): Tesla K80, Compute Capability 3.7 2019-02-28 00:15:41.055212: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2300025000 Hz 2019-02-28 00:15:41.055484: I tensorflow/compiler/xla/service/service.cc:150] XLA service 0x3fe90b0 executing computations on platform Host. Devices: 2019-02-28 00:15:41.055521: I tensorflow/compiler/xla/service/service.cc:158] StreamExecutor device (0): <undefined>, <undefined> 2019-02-28 00:15:41.056190: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1433] Found device 0 with properties: name: Tesla K80 major: 3 minor: 7 memoryClockRate(GHz): 0.8235 pciBusID: 0000:00:1e.0 totalMemory: 11.17GiB freeMemory: 11.11GiB 2019-02-28 00:15:41.056223: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0 2019-02-28 00:15:41.057198: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix: 2019-02-28 00:15:41.057230: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990] 0 2019-02-28 00:15:41.057255: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0: N 2019-02-28 00:15:41.057853: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 10805 MB memory) -> physical GPU (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7) tf.Tensor(54.97377, shape=(), dtype=float32)
うまくいったみたいです。