はじめに
Deep Leaningのモデル学習や物体検知(Object Detection)など,GPUを使って高速に処理を行いたい時があります。しかし、GPUを使った処理は、NVIDA系のGPUが必要となる場合が多く、ノートPCのCPUに内蔵されているIntel系のGPUは使えません💦eGPUを購入するという選択肢もありますが、ゲームをする訳でもないのでeGPUを買うのも躊躇します。そこで、考えるのがクラウドを使うという選択肢です。
そこで、AWSのEC2でGPUを搭載した仮想サーバを立ち上げ,DeepStreamやCUDA対応のOpenCVを利用する方法をまとめます。Ubuntsuの仮想サーバを立ち上げて、自力でNVIDA Driver、CUDA、TensorRT、DeepStream、OpenCVとインストールしても良いのですが、バージョンの不整合などなどで非常に苦労しました。そんな中見つけたのが,NVIDA DeepLeaning AMIとNVIDA DeepStream Dockerコンテナを利用する方法です。これを使うことで、1時間程度でDeepStreamとOpenCVが使えるようにできてしまいます。
用意するもの
用意するものは以下の1点だけです。昔だったら,NVIDAのGPUを使うためには,大きなPCケース、マザーボード、CPU、メモリ、GPUカードが必要だったのに,便利な世の中ですねー😍
①AWSアカウント
言わずとしれたAWSを利用するためのアカウントです。
作業手順
それでは、早速さくっとEC2上でDeepStream&OpenCV環境を構築していきましょう。
EC2インスタンス の立ち上げ
まずは、EC2上にGPUが使えるインスタンス を立ち上げていきます。AWS上でGPUが使えるインスタンスタイプは「AWSのGPU系EC2インスタンスをまとめてみた」でまとめて下さっているので、そちらを参照いただければと思います。今回はGPUが使える最も安い「g4dn.xlarge(0.75ドル/時間)」を使っていきます。なお、GPUインスタンス は無料枠で使える物はないので、多少お金がかかります💧
①制限の緩和
AWSの個人アカウントでは、GPUが使えるG系インスタンスの利用は制限されているので、制限緩和の申請を出す必要があります。申請と言っても簡単、EC2ダッシュボードの「制限」のメニューから「G instances」を検索して、「All G instranceのオンデマンドを実行」にチェックを入れて「制限緩和のリクエスト」を行うだけです。g4dn.xlargeは4cpuなので、緩和条件には「4」以上の数値を入力してくださいね。早ければ、1時間程度で制限緩和のメールが届きます。
②インスタンス の起動
制限緩和のメールが届いたら、EC2ダッシュボードの「インスタンス 」メニューから「インスタンス を起動」ボタンをクリックします。
②NVIDA Deep Leaning AMIの選択
DeepStreamを早く利用するためには、AMI の選択で「NVIDIA Deep Learning AMI」を利用することが最短ルートです。このAMIを利用することでNVIDA Driverが入ったインスタンスを利用できます。
手順としては、左メニューから「AWS Makerplace」を選択し、検索欄に「NVIDIA Deep Learning」と入力して検索します。検索結果に出てきた「NVIDIA Deep Learning AMI」の「選択」ボタンをクリックします。
利用料金に関する説明が表示されるので「Continue」ボタンをクリックします。ちなみに、このAMIは無料で使えます❗️すばらいいですね。
③インスタンスタイプの選択
インスタンスタイプの選択画面が表示されたら「すべてのインスタンスファミリー」ボタンをクリックし、リストから「g4dn」を選択します。
g4dnのインスタンスタイプがリストに表示されたら「g4dn.xlarge」を選択し「次のステップ:インスタンス の詳細設定」ボタンをクリックします。
④インスタンスの詳細の設定
インスタンス の詳細は、特に変更する必要はないので「次のステップ:ストレージの追加」ボタンをクリックします。
⑤ストレージの追加
DeepStreamのDockerイメージは10GBぐらいあるので、ルート(/dev/sda1)のサイズは「64GB」ぐらいに設定しておくことをお勧めします。
⑥タグの追加
タグの追加画面では、特に設定するものはないので「次のステップ:セキュリティグループの設定」ボタンをクリックします。
⑦セキュリティグループの設定
セキュリティグループの設定画面では、デフォルトでHTTPSと5000ポートが空いているので、これを削除しておくのが良いでしょう。
⑧インスタンス 作成の確認
最後にインスタンス 作成の確認画面が表示されるので「起動」ボタンをクリックします。
「起動」ボタンを押すと、以下のようにインスタンスが作成され、起動します。
⑨インスタンス の確認
インスタンス が起動したらSSHでログインしましょう。「/etc/os-release」を確認するとUbuntu 18.40ベースであることが確認できます。また「nvidia-smi」コマンドを実行するとNVIDIA Driverがインストール済みであること、GPUがTesla T4である事も確認できます。さらにDockerもインストール済みです。
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ nvidia-smi
Sun Jan 3 07:58:04 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla T4 On | 00000000:00:1E.0 Off | 0 |
| N/A 59C P8 11W / 70W | 0MiB / 15109MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
$ docker --version
Docker version 19.03.13, build 4484c46d9d
DeepStream Dockerコンテナの利用
「NVIDIA Deep Learning AMI」は、Deep Learningと名前が付きますが、単体ではDeepStreamを利用することはできません。そこで、DeepStreamを利用できるDockerコンテナ「Containers: nvidia:deepstream」を利用します。
①コンテナのダウンロード
Dokcerコンテナのダウンロードは簡単です。「docker pull nvcr.io/nvidia/deepstream:5.0.1-20.09-triton」と入力してダウンロードします。このコンテナは8GB程度あるのでダウンロードに5分程度かかります。
$docker pull nvcr.io/nvidia/deepstream:5.0.1-20.09-triton
5.0.1-20.09-triton: Pulling from nvidia/deepstream
423ae2b273f4: Pulling fs layer
de83a2304fa1: Pulling fs layer
f9a83bce3af0: Pulling fs layer
b6b53be908de: Pulling fs layer
・・・省略・・・
faa0a920b8d9: Pull complete
571e134596b4: Pull complete
Digest: sha256:15b1eaf3b85981cce5efb0fb0c8fd8f43a3695ed1f8f6f1a809b9c20ad777b4d
Status: Downloaded newer image for nvcr.io/nvidia/deepstream:5.0.1-20.09-triton
nvcr.io/nvidia/deepstream:5.0.1-20.09-triton
$
②Dockerイメージの確認
ダウンロードが完了したら「dockler images」コマンドでイメージを確認しましょう。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nvcr.io/nvidia/deepstream 5.0.1-20.09-triton 373b339eec8d 3 months ago 8.17GB
$
③Dockerイメージの起動
それでは、Dockerコンテナを起動しましょう‼️「–gpus all」オプションをつけてGPUを利用可能にすることがポイントです。また、ホームディレクトリなどを共用利用できるようにしておくと便利ですね。
$ docker run --gpus all -it --rm -v /home/ubuntu:/home/ubuntu -w /home/ubuntu nvcr.io/nvidia/deepstream:5.0.1-20.09-triton
④DeepStreamなどの確認
Dockerコンテナが起動したらDeepStreamなどが使えるか「deepstream-app -v」と入力して確認しましょう‼️ちゃんと「deepstream-app version 5.0.0」が使えます!さらにCUDAもロードできています。
$ deepstream-app -v
2021-01-02 12:50:05.641795: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.2
deepstream-app version 5.0.0
DeepStreamSDK 5.0.0
$
⑤nvccの確認
CUDAを使ったアプリのコンパイルに必要となる「nvcc」についても確認します。こちらもちゃんと使えます‼️CUDAのバージョンは10.2.89ですね。ちなみに、nvidia-smiコマンドのCUDAバージョンはあてになりません(笑)
$nvcc -V
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
OpenCVのインストール
ここからは、CUDAがインストール済みのDockerコンテナ上にCUDAに対応したOpenCVをインストールしていきます。
①必要パッケージのインストール
まずは、OpenCVに必要となるパッケージをインストールします。
# apt-get update
# apt-get install -y build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
# apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
# apt-get install -y python2.7-dev python3.6-dev python-dev python-numpy python3-numpy
# apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
# apt-get install -y libv4l-dev v4l-utils qv4l2 v4l2ucp
# apt-get install -y curl
# apt-get install -y unzip
②OpenCVのダウンロード
作業ディレクトリを作成し、OpenCVとOpenCV-contribをダウンロードして、解凍します。今回はOpenCV4.5.0を利用しました。
# mkdir opencv
# cd opencv/
# version="4.5.0”
# curl -L https://github.com/opencv/opencv/archive/${version}.zip -o opencv-${version}.zip
# curl -L https://github.com/opencv/opencv_contrib/archive/${version}.zip -o opencv_contrib-${version}.zip
# unzip opencv-4.5.0.zip
# unzip opencv_contrib-4.5.0.zip
③CMAKE
「release」ディレクトリを作成したら、以下のようにcmakeします。ポイントは「WITH_CUDA=ON」と「WITH_CUDNN=ON」を設定することです。また「CUDA_ARCH_BIN」にはTesla T4のアーキテクチャ番号である「7.5」を指定します。ここで指定するGPU Compute Capabilityの一覧はここから確認できます。
# cd opencv-4.5.0
# mkdir release
# cd release/
# cmake -D WITH_CUDA=ON -D WITH_CUDNN=ON -D BUILD_opencv_cudev=ON -D CUDA_ARCH_BIN="7.5" -D CUDA_ARCH_PTX="" -D OPENCV_GENERATE_PKGCONFIG=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.5.0/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
CMAKEが完了すると各種情報が表示れます。ポイントは97行目の「NVIDIA CUDA」の欄です。
-- General configuration for OpenCV 4.5.0 =====================================
-- Version control: unknown
--
-- Extra modules:
-- Location (extra): /home/ubuntu/opencv/opencv_contrib-4.5.0/modules
-- Version control (extra): unknown
--
-- Platform:
-- Timestamp: 2021-01-02T12:59:50Z
-- Host: Linux 5.4.0-1029-aws x86_64
-- CMake: 3.10.2
-- CMake generator: Unix Makefiles
-- CMake build tool: /usr/bin/make
-- Configuration: RELEASE
--
-- CPU/HW features:
-- Baseline: SSE SSE2 SSE3
-- requested: SSE3
-- Dispatched code generation: SSE4_1 SSE4_2 FP16 AVX AVX2 AVX512_SKX
-- requested: SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
-- SSE4_1 (15 files): + SSSE3 SSE4_1
-- SSE4_2 (1 files): + SSSE3 SSE4_1 POPCNT SSE4_2
-- FP16 (0 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
-- AVX (4 files): + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
-- AVX2 (29 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
-- AVX512_SKX (4 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2 AVX_512F AVX512_COMMON AVX512_SKX
--
-- C/C++:
-- Built as dynamic libs?: YES
-- C++ standard: 11
-- C++ Compiler: /usr/bin/c++ (ver 7.5.0)
-- C++ flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -DNDEBUG
-- C++ flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -g -O0 -DDEBUG -D_DEBUG
-- C Compiler: /usr/bin/cc
-- C flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -O3 -DNDEBUG -DNDEBUG
-- C flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -msse -msse2 -msse3 -fvisibility=hidden -g -O0 -DDEBUG -D_DEBUG
-- Linker flags (Release): -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a -Wl,--gc-sections -Wl,--as-needed
-- Linker flags (Debug): -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a -Wl,--gc-sections -Wl,--as-needed
-- ccache: NO
-- Precompiled headers: NO
-- Extra dependencies: m pthread cudart_static dl rt nppc nppial nppicc nppicom nppidei nppif nppig nppim nppist nppisu nppitc npps cublas cudnn cufft -L/usr/local/cuda/lib64 -L/usr/lib/x86_64-linux-gnu
-- 3rdparty dependencies:
--
-- OpenCV modules:
-- To be built: aruco bgsegm bioinspired calib3d ccalib core cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev datasets dnn dnn_objdetect dnn_superres dpm face features2d flann freetype fuzzy gapi hfs highgui img_hash imgcodecs imgproc intensity_transform line_descriptor mcc ml objdetect optflow phase_unwrapping photo plot python2 python3 quality rapid reg rgbd saliency shape stereo stitching structured_light superres surface_matching text tracking video videoio videostab xfeatures2d ximgproc xobjdetect xphoto
-- Disabled: world
-- Disabled by dependency: -
-- Unavailable: alphamat cnn_3dobj cvv hdf java js julia matlab ovis sfm ts viz
-- Applications: apps
-- Documentation: NO
-- Non-free algorithms: NO
--
-- GUI:
-- GTK+: YES (ver 3.22.30)
-- GThread : YES (ver 2.56.4)
-- GtkGlExt: NO
-- VTK support: NO
--
-- Media I/O:
-- ZLib: /usr/lib/x86_64-linux-gnu/libz.so (ver 1.2.11)
-- JPEG: /usr/lib/x86_64-linux-gnu/libjpeg.so (ver 80)
-- WEBP: build (ver encoder: 0x020f)
-- PNG: /usr/lib/x86_64-linux-gnu/libpng.so (ver 1.6.34)
-- TIFF: /usr/lib/x86_64-linux-gnu/libtiff.so (ver 42 / 4.0.9)
-- JPEG 2000: build (ver 2.3.1)
-- OpenEXR: /usr/lib/x86_64-linux-gnu/libImath.so /usr/lib/x86_64-linux-gnu/libIlmImf.so /usr/lib/x86_64-linux-gnu/libIex.so /usr/lib/x86_64-linux-gnu/libHalf.so /usr/lib/x86_64-linux-gnu/libIlmThread.so (ver 2_2)
-- HDR: YES
-- SUNRASTER: YES
-- PXM: YES
-- PFM: YES
--
-- Video I/O:
-- DC1394: YES (2.2.5)
-- FFMPEG: YES
-- avcodec: YES (57.107.100)
-- avformat: YES (57.83.100)
-- avutil: YES (55.78.100)
-- swscale: YES (4.8.100)
-- avresample: YES (3.7.0)
-- GStreamer: YES (1.14.5)
-- v4l/v4l2: YES (linux/videodev2.h)
--
-- Parallel framework: pthreads
--
-- Trace: YES (with Intel ITT)
--
-- Other third-party libraries:
-- Intel IPP: 2020.0.0 Gold [2020.0.0]
-- at: /home/ubuntu/opencv/opencv-4.5.0/release/3rdparty/ippicv/ippicv_lnx/icv
-- Intel IPP IW: sources (2020.0.0)
-- at: /home/ubuntu/opencv/opencv-4.5.0/release/3rdparty/ippicv/ippicv_lnx/iw
-- Lapack: NO
-- Eigen: NO
-- Custom HAL: NO
-- Protobuf: build (3.5.1)
--
-- NVIDIA CUDA: YES (ver 10.2, CUFFT CUBLAS)
-- NVIDIA GPU arch: 75
-- NVIDIA PTX archs:
--
-- cuDNN: YES (ver 7.6.5)
--
-- OpenCL: YES (no extra features)
-- Include path: /home/ubuntu/opencv/opencv-4.5.0/3rdparty/include/opencl/1.2
-- Link libraries: Dynamic load
--
-- Python 2:
-- Interpreter: /usr/bin/python2.7 (ver 2.7.17)
-- Libraries: /usr/lib/x86_64-linux-gnu/libpython2.7.so (ver 2.7.17)
-- numpy: /usr/lib/python2.7/dist-packages/numpy/core/include (ver 1.13.3)
-- install path: lib/python2.7/dist-packages/cv2/python-2.7
--
-- Python 3:
-- Interpreter: /usr/bin/python3 (ver 3.6.9)
-- Libraries: /usr/lib/x86_64-linux-gnu/libpython3.6m.so (ver 3.6.9)
-- numpy: /usr/local/lib/python3.6/dist-packages/numpy/core/include (ver 1.18.2)
-- install path: lib/python3.6/dist-packages/cv2/python-3.6
--
-- Python (for build): /usr/bin/python2.7
--
-- Java:
-- ant: NO
-- JNI: NO
-- Java wrappers: NO
-- Java tests: NO
--
-- Install to: /usr/local
-- -----------------------------------------------------------------
--
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/opencv/opencv-4.5.0/release
④ビルド
CMAKEが完了したらOpenCVをビルドします。g4dn.xlargeはCPUを4つ搭載しているので「-j4」オプションを使って4つのCPUを使うと早く終わります。といっても、ビルドには30分ぐらい掛かるので、気長に待ちましょう☕️ビルドが完了したら「make install」ですね。
#make -j4
・・・・
#make install
⑤OpenCVの確認
make installしたらOpenCVを確認しましょう。ちゃんとPythonからOpenCVが使えています!
# python3
Python 3.6.9 (default, Oct 8 2020, 12:12:24)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.5.0'
>>> exit()
【参考】Docker commit
私はいつも「docker commit」を忘れて、せっかくインストールしたものが消えてしまい泣くので、備忘録として書いておきます。Dockerを使う時は注意ですね💦
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f476a68db4f1 nvcr.io/nvidia/deepstream:5.0.1-20.09-triton "/opt/nvidia/deepstr…" 27 minutes ago Up 27 minutes nifty_edison
$ docker commit f476a68db4f1 deepstream_opencv
sha256:8ba1fe9e65f2a18e4eb2ed82d2e7f304628f69fb971f0db5614d277b3e3ab377
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
deepstream_opencv latest 8ba1fe9e65f2 18 seconds ago 8.82GB
nvcr.io/nvidia/deepstream 5.0.1-20.09-triton 373b339eec8d 3 months ago 8.17GB
おわりに
今回はGPUを使ったDeep LearningやObject Detectionを行うことを目的に、AWS EC2上でDeepStream、CUDA対応のOpenCVを利用する方法をご紹介しました。GPUを搭載したマシンが無くても、時間単位でGPUマシンが使えるのは非常に便利ですね!ただし、g4dn.xlargeは1時間に75円ほどお金がかかるので、インスタンス のあげっぱなしには注意が必要です!
コメント