Docker on GPU インスタンス(EC2)で CUDA コンテナの実行環境を作って Hello World を実行してみた
CUDA の動作確認環境として、CUDA のコンテナを利用した実行環境を用意する機会がありました。Hello World を実行するまでの過程を例に GPU インスタンス上で CUDA コンテナの実行環境の構築方法を紹介します。
検証環境
検証環境の構成です。
Inventory icons created by Freepik - Flaticon
Name | Version |
---|---|
Instance Type | g4dn.xlarge |
AMI Name | Deep Learning Base AMI (Amazon Linux 2) Version 58.2 |
AMI I | ami-0921844ed281cc082 |
OS | Amazon Linux 2 |
Docker | 20.10.23 |
Docker Image | nvidia/cuda:10.2-devel-centos7 |
CUDA | 10.2.89 |
CUDA コンテナ実行環境の準備
NVIDIA ドライバーのセットアップに時間がかかるため、素の GPU インスタンスの AMI を使用するのではなく、Deep Learning AMI を使用することをオススメします。また、CUDA をインストール済みの AMI(Deep Learning GPU CUDA)も提供されていますが、本検証では、CUDA をコンテナイメージ側で管理するため、ホストにはインストールしないことにします。
- AMI Name: Deep Learning Base AMI (Amazon Linux 2) Version 58.2
- Instance Type: g4dn.xlarge
GPU インスタンスは比較的高額なため、スポットインスタンスを使用して検証を行います。検証には最新の g5.xlarge インスタンスタイプを使用したかったのですが、キャパシティ不足のため起動できませんでした。そのため、スポットインスタンスでも起動可能だった g4dn.xlarge を使用しています。
Docker の準備
Deep Learning AMI はすでに Docker がインストール済みでした。現時点での Docker Engine の最新バージョンは24.0.2
でした。最新ではありませんがそのまま利用します。
Docker Engine 24.0 release notes | Docker Documentation
$ docker version Client: Version: 20.10.23 API version: 1.41 Go version: go1.18.9 Git commit: 7155243 Built: Tue Apr 11 22:56:36 2023 OS/Arch: linux/amd64 Context: default Experimental: true Server: Engine: Version: 20.10.23 API version: 1.41 (minimum version 1.12) Go version: go1.18.9 Git commit: 6051f14 Built: Tue Apr 11 22:57:17 2023 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.19 GitCommit: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f runc: Version: 1.1.5 GitCommit: f19387a6bec4944c770f7668ab51c4348d9c2f38 docker-init: Version: 0.19.0 GitCommit: de40ad0
CUDA コンテナイメージの準備
NVIDIA 謹製の CUDA イメージを利用します。CUDA のソースコードをコンパイルするためnvcc
コマンドが利用可能なdevel
のイメージを使います。
今回は CUDA 10. 代 + CentOS 7 の環境をコンテナで動作するか検証が必要だったため、あえて古いバージョンのコンテナイメージを利用しています。
- Docker Image: nvidia/cuda:10.2-devel-centos7
CUDA コンテナの起動
コンテナ内でコンパイルしたバイナリファイルをローカル(GPU インスタンス)と共有できるように作業用のディレクトリをマウントします。
先にマウント用のディレクトリを作成しておきます。
mkdir $(pwd)/work
GPU を利用するコンテナ起動時のポイントは--gpus=all
フラグが必要です。
docker run \ --gpus=all \ -it \ -v "$(pwd)"/work:/work \ nvidia/cuda:10.2-devel-centos7 \ bash
以下のメッセージが表示されていれば成功です。
========== == CUDA == ========== CUDA Version 10.2 Container image Copyright (c) 2016-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. This container image and its contents are governed by the NVIDIA Deep Learning Container License. By pulling and using the container, you accept the terms and conditions of this license: https://developer.nvidia.com/ngc/nvidia-deep-learning-container-license A copy of this license is made available in this container at /NGC-DL-CONTAINER-LICENSE for your convenience. ************************* ** DEPRECATION NOTICE! ** ************************* THIS IMAGE IS DEPRECATED and is scheduled for DELETION. https://gitlab.com/nvidia/container-images/cuda/blob/master/doc/support-policy.md
CUDA コンテナを使ってみる
CUDA コンテナにログインできました。コンテナ内であれば必要なコマンドが利用可能なはずです。Hello World コードをコンパイルして実行まで試してみます。
nvcc
コマンドが利用可能かチェックします。devel
のイメージはコンパイル作業に利用できることが確認できました。
# nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2019 NVIDIA Corporation Built on Wed_Oct_23_19:24:38_PDT_2019 Cuda compilation tools, release 10.2, V10.2.89
Hello World コードは下記リンクを参考にしました。
__global__
の指定があると GPU 上で実行する関数となります。
#include <stdio.h> __global__ void helloFromGPU(void) { printf("Hello World From GPU!\n"); } int main(void) { printf("Hello World from CPU!\n"); helloFromGPU<<<1,10>>>(); cudaDeviceReset(); return 0; }
コンパイルします。
nvcc hello.cu -o hello
バイナリが生成されました。CUDA コンテナを利用してコンパイルまでは正常に行えることを確認できました。
# ll total 640 -rwxr-xr-x 1 root root 650000 Jun 7 05:59 hello -rw-r--r-- 1 root root 222 Jun 6 08:04 hello.cu
バイナリを実行してみると GPU 上で実行された関数の結果(Hello World From GPU!
のメッセージ)を確認できました。
# ./hello Hello World from CPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU! Hello World From GPU!
GPU からのメッセージが返ってこないケース
コンテナ起動時に--gpus=all
フラグを付け忘れたとしましょう。
docker run \ -it \ -v "$(pwd)"/work:/work \ nvidia/cuda:10.2-devel-centos7 \ bash
すると、コンテナから GPU を利用できずに CPU 上で実行した関数の結果しか返ってきません。
# ./hello Hello World from CPU!
コンテナが NVIDIA GPU リソースへアクセスするためには--gpus
フラグが必須ですので注意しましょう。
おわりに
CUDA を扱ったことがなかったので単純なプログラムで動作環境の検証したかったので Hello World を試してみました。そんな実行環境の作り方紹介でした。はじめて GPU コンテナを使ってみたのですけどコンテナだと CUDA のバージョン指定が楽で使い勝手が良いですね。