おぺんcv

画像処理エンジニアのブログ

OpenCVのDNNモジュールがCUDAバックエンドに対応した

はじめに

1年ちょっとぶりにブログ更新しました、お久しぶりです

さて、去年12月にOpenCVの最新バージョンであるOpenCV 4.2.0がリリースされました
そのChange Logをみると嬉しい更新が

DNN module:

Integrated GSoC project with CUDA backend: #14827

DNNモジュールにCUDAバックエンドが追加され、ついにNVIDIA GPUでもDNNを動かせるようになったようです!

そこで今回は、手持ちのGPUで実際にDNNモジュールが速くなるのか検証してみました
結果だけ知りたい方は目次から計測結果に飛んでください

目次

環境構築

CUDAバックエンドに対応するために、OpenCV 4.2.0をソースからビルドします
私のビルド環境は以下の通りです

また、追加で以下が必要になります

cuDNNのインストール

手持ちのCUDA Toolkitのバージョンに対応したcuDNNをダウンロード・解凍し、
bin,include,libの中身をCUDA Toolkitの同名のフォルダ以下にコピーしておきます

CMakeの設定

CMake(cmake-gui)を立ち上げ、ソースとビルドのパスを指定したら一旦Configure
次に以下の項目を設定していきます

  • WITH_CUDAにチェック
  • OPENCV_DNN_CUDAにチェック
  • OPENCV_EXTRA_MODULES_PATHoepncv_contrib/modulesのパスを設定
  • CUDA_ARCH_BINから古いバージョン番号を消す※

設定したら再度Configureし、問題なければGenerateでプロジェクトを作成
あとはビルドしてひたすら待ちましょう!

CUDA_ARCH_BINはデフォルトで3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5と設定されていると思いますが、そのままConfigureしたら以下のエラーが発生

CUDA backend for DNN module requires CC 5.3 or higher.  Please remove
unsupported architectures from CUDA_ARCH_BIN option.

DNNモジュールは古いバージョンのCUDAに対応してないようです
自分のGPUはGTX 1080(SM61)なので6.1以上のものだけ残しました

計測用コード作成

前回記事で紹介したSemantic Segmentationのサンプルopencv/samples/dnn/segmentation.cppを使用します(ネットワークも前回同様Enetです)

推論処理net.forward()の前後にタイマーを挟んで、適当回数実行した際の中央値をとります

さて、CUDAバックエンドを有効化する方法は使い方はいたって簡単で、実行時の引数に以下を追加するだけ!

--backend=5 --target=6

これはそれぞれネットワークにDNN_BACKEND_CUDA(=5)DNN_TARGET_CUDA(=6)を設定していることになります

比較用に、ターゲットをCPU(--target=0)とOpenCL(--target=1)に設定した際の処理時間も計測しました

計測結果

計算機は以下の通りです

入力サイズ1024×512に対するEnetの推論時間はおおよそ以下の通りになりました

CPU OpenCL CUDA
350[milli sec] 100[milli sec] 21[milli sec]

さすがCUDAバックエンドは圧倒的に速いですね!このサイズで50FPS近く出るのは驚きです

次いでOpenCLですが、実のところOpenCLを指定した際にどのデバイスで実行されているのかよく知りません…(CPUよりは速くなってるので、内蔵GPUで動いてるのかな?)

おわりに

CUDAバックエンドに対応したDNNモジュールを動かし、高速に動作することを確認しました
DNNを利用したアルゴリズム開発において、OpenCVが一層便利になったのではないでしょうか!