OpenCLでOpenCV
OpenCLとは?
OpenCL (Open Computing Language) とは,ヘテロジニアスコンピューティングを実現するためのフレームワークで,OpenCL C/OpenCL C++言語を用いて記述します.平たく言えば「並列計算のためのフレームワーク」ということです.CUDAより汎用的なプラットフォームである,というか,そもそもOpenCLはCUDAと違い,GPGPUのためだけのフレームワークではありません (参考・CUDAとOpenCLどっちがいいの?).AMDのGPUでGPGPUをしたい場合はOpenCLが良いということなので,MacBookとかでGPGPUをしたいときはOpenCLを使うとよいのではないでしょうか (無責任ですが).
OpenCVでOpenCLを使うには
OpenCVのインストーラ版は,OpenCV 2.4.7以降でOpenCLが有効化されているそうです.OpenCV3.0以降では,
#include <opencv2/core/ocl.hpp>
とするとOpenCLのモジュールを使用可能になります.
OpenCLを使うテストコード
OpenCV 3.0.0での独自カーネルOpenCLを参考にさせていただきました.
#ifdef _DEBUG #pragma comment (lib, "opencv_world310d.lib") #else #pragma comment (lib, "opencv_world310.lib") #endif // _DEBUG #pragma comment (lib, "winmm.lib") #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> #include <Windows.h> #include <MMSystem.h> // for framerate measurement int main( int argc, char** argv ) { // OpenCLがこのシステムで使えるかチェック if( !cv::ocl::haveOpenCL() ) { std::cout << "OpenCL not available on this system" << std::endl; return -1; } // コンテクストの宣言 cv::ocl::Context context; if( !context.create( cv::ocl::Device::TYPE_GPU ) ) { std::cout << "Context creation failed" << std::endl; return -1; } // デバイスの列挙 std::cout << context.ndevices() << " GPU device(s) detected" << std::endl; for( size_t i = 0; i < context.ndevices(); i++ ) { cv::ocl::Device device = context.device( i ); std::cout << "-- Device " << i << " ---" << std::endl; std::cout << " Name: " << device.name() << std::endl; std::cout << " Availability: " << device.available() << std::endl; std::cout << " Image Support: " << device.imageSupport() << std::endl; std::cout << " OpenCL C version: " << device.OpenCL_C_Version() << std::endl; } // 列挙はしたが,結局デバイス0番を用いる cv::ocl::Device( context.device( 0 ) ); cv::Mat mSrc = cv::imread( "./lena.jpg", cv::IMREAD_GRAYSCALE ); cv::UMat src = mSrc.getUMat( cv::ACCESS_READ ); const int TEST_COUNT = 10000; // 実行時間計測 static DWORD timeCP0, timeCP1; // OpenCL Enable状態でSobelをTEST_COUNT回ループ cv::ocl::setUseOpenCL( true ); std::cout << "Sobel Test: OpenCL Enabled"; // フレームレート計測モジュール timeCP0 = timeGetTime(); for( int i = 0; i < TEST_COUNT; i++ ) { cv::UMat dst; cv::Sobel( src, dst, -1, 1, 0 ); } timeCP1 = timeGetTime(); std::cout << " --- Done. Processing Time: " << ( float )( timeCP1 - timeCP0 ) / 1000 << " sec." << std::endl; // OpenCL Disable状態でSobelをTEST_COUNT回ループ cv::ocl::setUseOpenCL( false ); std::cout << "Sobel Test: OpenCL Disabled" ; timeCP0 = timeGetTime(); for( int i = 0; i < TEST_COUNT; i++ ) { cv::UMat dst; cv::Sobel( src, dst, -1, 1, 0 ); } timeCP1 = timeGetTime(); std::cout << " --- Done. Processing Time: " << ( float )( timeCP1 - timeCP0 ) / 1000 << " sec." << std::endl; return 0; }
実行結果
1 GPU device(s) detected
-- Device 0 ---
Name: Intel(R) Iris(TM) Pro Graphics 550
Availability: 1
Image Support: 1
OpenCL C version: OpenCL C 2.0
Sobel Test: OpenCL Enabled --- Done. Processing Time: 2.63 sec.
Sobel Test: OpenCL Disabled --- Done. Processing Time: 28.063 sec.
となり,手元の環境では有意に速い.