#はじめに
- この記事は、OpenCV Advent Calendar 2017 16日目の記事です。
- 予定では、”仮) OpenCV 3.4 RC版で何か” を書く予定でしたが、まだRC版がリリースされていないので変更しました。
- 代わりに、今年のAdvent Calendar でも高速化に関していくつかエントリーされており、特に3日目の記事 ASUS tinker boardのMali T764をOpenCV 3.3.1のOpenCLで酷使してみる を読み気になったので、OpenCL を利用している UMat を試してみた。
- 実は、4年前にOpenCLを試してみたことがあったのですが、想像していたよりも使えなかったために、それ以降触れる機会がほとんどありませんでした。
##UMatとは
-
UMatは、OpenCV 3.0 から取り入れられた高速化の手法の1つです。OpenCL をベースとしており、OpenCV 2系では、OCLクラスとして実装されていました。
-
3系でもOCLクラスは、実装されていますが、OCLクラスを意識しなくても、利用できるようになっており、"Transparent API" designと呼ばれています。
##テスト環境
マシンスペック
- CPU Intel(R) Core(TM) i3-6006U CPU @ 2.00GHz
- グラフィックス: Intel(R) HD Graphics 520
とほぼエントリーマシンに近い性能のものです。
ソフトウェア
- ほとんど素に近いWindows10 Home 64bit
- windwos 版バイナリの OpenCV 3.3.1 ダウンロードして展開
- Visual Studio 2017 community Editionをインストール
今では、OpenCL SDK は、インストールしなくても利用できるようになっているようです。
##テストプログラム
- 今回時間があまりとれませでしたので、OpenCVの定番である顔検出に利用される detectMultiScale で処理時間を計測しました。パラメータは、デフォルトのままです。
- CPU 利用の Mat と グラフィックスモジュール利用の UMat を用い、ばらつきを抑えるため10回実行の平均値を求めています。
- また、UMatに関しては、カーネルのコンパイル時間が加算される1回めを計測から外し、また、グラフィックスモジュールへのデータ転送と ch変換の処理時間も別途計測しています。
- 計測対象の画像は、お馴染みのLena、画像サイズは、512 x 512
##ソース
計測プログラムから、関連部分のみ抜粋
インクルード関連
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>
#pragma comment(lib, "opencv_world331d.lib")
Matによる10回計測部
cv::Mat mat = cv::imread("c:\\tmp\\lena.jpg");
cv::CascadeClassifier faceCascade("c:\\tmp\\haarcascade_frontalface_alt.xml");
std::vector<cv::Rect> facesM, facesU;
cv::TickMeter t1;
t1.start();
for (int i = 0; i < 10; i++) {
faceCascade.detectMultiScale(mat, facesM);
}
t1.stop();
UMat 最初の計測部。この時、カーネルのバイナリコードがコンパイルされ、メモリにキャッシュされるために、2回め以降は、コンパイルのオーバーヘッドがない。
cv::TickMeter t2;
t2.start();
cv::UMat umat = mat.getUMat(cv::ACCESS_READ);
t2.stop();
t2.reset();
t2.start();
faceCascade.detectMultiScaleumat, facesU);
t2.stop();
UMatによる 10計測部
cv::TickMeter t3;
t3.start();
for (int i = 0; i < 10; i++) {
umat = mat.getUMat(cv::ACCESS_READ);
}
t3.stop();
t3.reset();
t3.start();
for (int i = 0; i < 10; i++) {
faceCascade.detectMultiScale(umat, facesU);
}
t3.stop();
##計測結果
Mat 10回平均の処理時間
- detectMultiScale 211.374ms
UMat 1回め処理時間
- 作成 0.238522ms
- detectMultiScale 1196.11ms
UMat 10回平均の処理時間
- 作成 0.0102297ms
- detectMultiScale 84.8129ms
##結論
エントリーマシンでも、一部のAPIに限定されるが、従来のソースへの少しの変更点で、高速化の恩恵を受けることが確認できた。
##UMat の使用上の注意
- 一部のAPIしか対応していません。
- 最初の呼び出しでは、カーネルコンパイルのオーバヘッドが生じる
- CPUでの計算結果と一致しない場合がある。
- デフォルトでは、最初に認識されたGPUベースのOpenCLデバイスが使用される。変更できるが簡単ではない
##最後に
明日は、te20 さんの番です。
今回、時間の都合で省いたことをBlogに追記する予定です。