【OpenCV开发】使用OpenCV的OpenCL(ocl)模块
參加OpenCV的OpenCL模塊(以下稱OCL)移植工作已經(jīng)有2個(gè)月了。這里我說移植而不是開發(fā),是因?yàn)榇蟛糠諳CL模塊的函數(shù)都是從已經(jīng)很成熟的GPU模塊移植過來的。于是目前階段OCL模塊所支持的函數(shù)接口只是GPU模塊的一個(gè)子集。
OpenCV的版本控制系統(tǒng)已經(jīng)轉(zhuǎn)移到了git上面(見https://github.com/itseez/opencv),最新的trunk的master分支正式加入了OCL模塊。今天逛OpenCV的開發(fā)者社區(qū),我發(fā)現(xiàn)有人提問在OpenCV庫(kù)中如何進(jìn)行使用OCL模塊的函數(shù);回答問題的同時(shí),由于網(wǎng)上還沒有針對(duì)OpenCV的OCL模塊的資料,我決定寫一篇文章簡(jiǎn)單介紹下OCL模塊以方便開發(fā)者使用。
Introduction to OpenCL
對(duì)于OpenCL已經(jīng)有所了解的,可以直接跳過這一節(jié)。
"OpenCL是用于編寫在異構(gòu)平臺(tái)上運(yùn)行程序的框架,所謂異構(gòu)平臺(tái),一般情況我們指GPU和CPU兩種處理器混合的平臺(tái)。OpenCL由一門用于編寫kernels (在OpenCL設(shè)備上運(yùn)行的函數(shù))的語言(基于C99)和一組用于定義并控制平臺(tái)的API組成。"?
OpenCL可以實(shí)現(xiàn)GPGPU(General-purpose computing on graphics processing units, 通用圖形處理器)運(yùn)算, "是一種利用處理圖形任務(wù)的GPU來計(jì)算原本由CPU處理的通用計(jì)算任務(wù)。這些通用計(jì)算常常與圖形處理沒有任何關(guān)系。由于現(xiàn)代圖形處理器強(qiáng)大的并行處理能力和可編程流水線,令流處理器可以處理非圖形數(shù)據(jù)。特別在面對(duì)單指令流多數(shù)據(jù)流(SIMD),且數(shù)據(jù)處理的運(yùn)算量遠(yuǎn)大于數(shù)據(jù)調(diào)度和傳輸?shù)男枰獣r(shí),通用圖形處理器在性能上大大超越了傳統(tǒng)的中央處理器應(yīng)用程序。" -- 摘自wikipedia
簡(jiǎn)單解釋一下這段話中幾個(gè)重點(diǎn):
利用GPU強(qiáng)大的并行能力代替CPU進(jìn)行運(yùn)算
GPU的并行能力特別適合于關(guān)于矩陣的運(yùn)算。利用GPU,我們可以發(fā)起很多個(gè)輕量級(jí)線程,每個(gè)線程僅處理一個(gè)元素的計(jì)算來實(shí)現(xiàn)數(shù)據(jù)并行;而對(duì)于CPU,我們只能按順序每個(gè)元素迭代運(yùn)算。GPU和CPU運(yùn)算對(duì)比起來可以想象成4輛坦克與1萬個(gè)士兵的戰(zhàn)斗力水平的對(duì)比;孰勝孰劣,還要看具體進(jìn)行的任務(wù)。因此,并不是所有的OpenCV函數(shù)都適合移植到GPU上進(jìn)行運(yùn)算。
OpenCL由在OpenCL設(shè)備上運(yùn)行的kernel函數(shù)語言和控制平臺(tái)的API組成
OpenCL包含兩個(gè)主要部分:device和host。在CPU和GPU組成的異構(gòu)平臺(tái)中,我們一般把運(yùn)行核函數(shù)的GPU處理器部分稱為device,把控制平臺(tái)API的CPU稱為host。相應(yīng)的,把host上的內(nèi)存(就是內(nèi)存)稱為host memory;而把device上的內(nèi)存(GPU顯存)稱為device memory或者device buffer。在OpenCV里,我們把這兩種內(nèi)存封裝為cv::Mat和cv::ocl::oclMat結(jié)構(gòu)。
數(shù)據(jù)調(diào)度和傳輸
OpenCV的OCL模塊中,在GPU上進(jìn)行運(yùn)算之前我們必須把內(nèi)存轉(zhuǎn)成GPU可以直接調(diào)用的顯存。而在GPU上的運(yùn)算結(jié)束后,我們還需要將在GPU顯存上的數(shù)據(jù)轉(zhuǎn)移到CPU可用的內(nèi)存上。這兩個(gè)操作在oclMat中定義為兩個(gè)成員函數(shù),分別為oclMat::download和oclMat::upload。由于這兩個(gè)數(shù)據(jù)傳輸操作受PCI總線寬帶的限制,在實(shí)際應(yīng)用中應(yīng)盡量減少數(shù)據(jù)傳輸,把盡可能多的運(yùn)算在gpu device上計(jì)算完成后,再把數(shù)據(jù)傳回cpu host,以達(dá)到最大的數(shù)據(jù)吞吐量。
OpenCV's CUDA Module
介紹OpenCL模塊前,不得不先提一下OpenCV的GPU(以下特指CUDA模塊)模塊。由于OCL模塊是直接移植自GPU的代碼,所以我們可以先來了解下他的前身。
來源:http://opencv.org/platforms/cuda.html
歷史
GPU模塊最初由NVIDIA公司在2010年起支持開發(fā),2011年春發(fā)布了第一個(gè)帶有GPU模塊的OpenCV版本。GPU模塊包含并加速了很大一部分原先只能運(yùn)行在CPU設(shè)備上的庫(kù)函數(shù),并且隨著新的計(jì)算技術(shù)和GPU架構(gòu)不斷發(fā)展和更新。
目標(biāo)
?
?
性能
模塊設(shè)計(jì)
OpenCV的GPU模塊還加入了CUDA第三方函數(shù)的支持,如NVIDIA NPP和CUFFT。(相應(yīng)的,OCL模塊也加入了AMD提供的amdBlas和amdFft庫(kù))
GPU模塊被設(shè)計(jì)成host上能調(diào)用的CUDA API擴(kuò)展集。這個(gè)設(shè)計(jì)模式讓開發(fā)者能明確的控制數(shù)據(jù)在CPU和GPU的內(nèi)存間的傳輸。盡管用戶必須要多寫一點(diǎn)代碼來開始使用GPU模塊,但是這個(gè)過程是靈活的,并且允許用戶對(duì)GPU數(shù)據(jù)控制的代碼進(jìn)行優(yōu)化。
GPU模塊的gpu::GpuMat類是一個(gè)封裝了儲(chǔ)存在在GPU顯存的容器,而他的接口與CPU的cv::Mat類非常相似。所有的GPU模塊函數(shù)以GpuMat作為輸入輸出函數(shù),這樣的設(shè)計(jì)允許多個(gè)GPU算法在數(shù)據(jù)不下載到CPU內(nèi)存就能完全調(diào)用,增加了數(shù)據(jù)吞吐效率。并且GPU函數(shù)接口也盡可能的和CPU函數(shù)保持移植,這樣熟悉OpenCV CPU操作的開發(fā)者能直接轉(zhuǎn)移到GPU模塊上進(jìn)行開發(fā)。
由于OpenCL的開發(fā)模式與CUDA非常類似,包括host API和device上運(yùn)行的核函數(shù)語法,所以移植工作并不困難。移植過程中,我們保持了GPU模塊的設(shè)計(jì)理念,并且在保證代碼質(zhì)量的基礎(chǔ)上,盡可能的讓OCL模塊的函數(shù)跟上GPU模塊的更新節(jié)奏。
-----------------------------------------------------------------------------------
Compile Latest OpenCV trunk repository
以下以windows 7 32bit + visual studio 2010 + AMD顯卡為例。
由于ocl模塊剛剛加入OpenCV的主版本,用戶想要基于ocl開發(fā)的話,需要從OpenCV的git服務(wù)器上pull一下最新trunk repository的OpenCV代碼。git地址如下:
git://code.opencv.org/opencv.git
或者github的鏡像
https://github.com/itseez/opencv
下載完成后,你還需要一個(gè)新的OpenCL SDK。以AMD顯卡系列為例,APP SDK v2.7下載地址http://developer.amd.com/sdks/amdappsdk/downloads/pages/default.aspx
你還需要CMake2.8版本來生成Visual Studio的sln項(xiàng)目。cmake的使用方法就不多說了,網(wǎng)上有很詳細(xì)的教程。
應(yīng)注意的是在用CMake對(duì)OpenCV項(xiàng)目進(jìn)行配置時(shí),要手動(dòng)打開WITH_OPENCL選項(xiàng),這個(gè)是默認(rèn)關(guān)閉的。如果一切正常的話,在CMake的命令行輸出終究會(huì)提示找到OpenCL的靜態(tài)庫(kù)和include文件夾;如果提示沒有找到的話,需要自己手動(dòng)在cmake中找到這兩個(gè)選項(xiàng),添加include文件夾和動(dòng)態(tài)庫(kù)路徑。
上面步驟完成后,就可以打開OpenCL.sln文件編譯OpenCV了~
Using OCL module
使用ocl模塊的方法跟gpu非常類似(本來就是無腦無縫移植什么的)。調(diào)用ocl模塊的任何模塊前,必須明確的調(diào)用一下ocl名字空間下的getDevice函數(shù)。
上文提到,所有的ocl模塊調(diào)用的矩陣類型格式是oclMat。oclMat跟Mat結(jié)構(gòu)類似,包含大部分的成員函數(shù)和成員變量,但是最重要的是封裝了OpenCL的buffer數(shù)據(jù)(cl_mem)并控制他的內(nèi)存釋放與傳輸。
把一個(gè)Mat轉(zhuǎn)化成oclMat非常簡(jiǎn)單,你可以調(diào)用oclMat的構(gòu)造函數(shù):
[cpp]?view plaincopy
[cpp]?view plaincopy
[cpp]?view plaincopy
概括地說,使用ocl模塊有這么幾個(gè)過程:
?
下載到的OpenCV的trunk代碼中包含了幾個(gè)OpenCL的sample程序可以作為開發(fā)者的參考。
謝謝閱讀~
鵬?
August 19, 2012
【原文地址】http://blog.csdn.net/pengx17/article/details/7880642
轉(zhuǎn)載于:https://www.cnblogs.com/huty/p/8517556.html
總結(jié)
以上是生活随笔為你收集整理的【OpenCV开发】使用OpenCV的OpenCL(ocl)模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mac os下安装brew
- 下一篇: AC日记——字符替换 openjudge