0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

cv::UMatがいまいちだった件(グラボなしGPU利用)

Posted at

はじめに

近年、人工知能などで莫大な計算量や情報量が要求されるソフトウェアが増えている。
これを処理するために、「CPUだけ」での能力では役不足になってきている。
そこで注目されるのは、以前は映像処理専門だったグラフィックボード(GPU)である。
これは、映像処理はもちろんの事、大容量の専用メモリーがあり、処理能力もCPUに引けを取らいないものであれば、データをGPUにアップロードして、処理をGPUに投げて、処理完了後にダウンロードして結果を受け取れば、CPUはその空き時間で別の処理を行うことが可能である。また、GPUは専用メモリーを使うので、メインメモリの圧迫が軽減されることが期待される。
OpenCVでは「GpuMat」と言う、GPUで処理させるMatが存在するが、これを利用するにはN社製のグラフィックボードとCUDAのインストールがあって、初めて利用可能となる。
逆に言えば、初めからマザーボードに張り付いている、I社製などのGPUでは利用することは出来ない。
そこで登場するのが「UMat」である。UMatはGpuMatが使えない環境でも、OpenCVからGPUを利用することが出来る。これを使用することでソフトウェアの動作速度の向上などが期待されるのである。

UMatの簡単な使い方

UMatは概念的には仮想のデバイスであり、直接そのメモリ空間にアクセスする事は出来ない。これはGpuMatでも同様である。
そこで一旦Matにデータをセットして、それをCopyTo()関数でアップロードする。
処理が終わったらCopyTo()関数でダウンロードする。

test.cpp

int main()
{
    cv::Mat  img;
    cv::Mat  gray;
    cv::UMat u_img;
    cv::UMat u_gray;
    //画像読み込み
    img = cv::imread("apple.jpg");

    //UMatへアップロード
    img.copyTo(u_img);

    //Gpuで処理する内容を記述(この場合はカラーからグレイスケール変換)
    cv::cvtColor(u_img,u_gray,cv::COLOR_BGR2GRAY);

    //Matへダウンロード
    u_gray.copyTo(gray);

    //表示
    cv::imshow("gray",gray);
    //u_grayを直接表示する事も可能
    cv::imshow("u_gray",u_gray);

    cv::waitKey();
}

apple.jpg

u_gray.jpg

UMatの簡単なベンチマーク

以下のようなコードを記述して、実行時間を計測した。

u_time.cpp

#include <opencv2/opencv.hpp>
#include <windows.h>
#include <stdio.h>



int main(int argc, char* argv[])
{
	const int LOOP_NUM = 100;

	cv::Mat src = cv::imread("apple.jpg");

	cv::Mat gray;
	DWORD   st;
	//UMat時間計測開始
	st = GetTickCount();
	//アップロード
	cv::UMat u_src;
	cv::UMat u_gray;
	src.copyTo(u_src);
	//時間稼ぎループ
	for(int cnt=0;cnt < LOOP_NUM;cnt++)
	{
		//グレイスケール画像に変換
		cv::cvtColor(u_src,u_gray,cv::COLOR_BGR2GRAY);
	}
	//ダウンロード
	u_gray.copyTo(gray);
	//UMat時間計測完了
	std::cout << "UMat時間" << GetTickCount() -  st << "[ms]" << std::endl;
	//UMat画像表示
	cv::imshow("u_gray",gray);
	cv::waitKey(30);

	//Mat時間計測開始
	st = GetTickCount();
	//時間稼ぎループ
	for(int cnt=0;cnt < LOOP_NUM;cnt++)
	{
		//グレイスケール画像に変換
		cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
	}
	//Mat時間計測完了
	std::cout << "Mat時間" << GetTickCount() -  st << "[ms]" << std::endl;
	//Mat画像表示
	cv::imshow("Mat",gray);
	cv::waitKey();

	return 0;
}

実行時間

UMat時間 7719[ms]
Mat時間 78[ms]

以上からUMatの方が著しく遅い結果となった。

おわりに

Umatの実行時間はよろしくなかったが、実際別件でUmatを組み込んで使って見ても、
速度性能向上は見られず、かえってメモリ違反などが出ていたので、
ある意味予想通りだった。
C/C++プログラマであれば、ポインタやC言語の標準関数などを駆使するのが、
現実的と考える。
Windowsであれば、Direct3D/2Dの利用を検討するのもありかと思います。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?