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