來源:http://blog.csdn.net/leonwei/article/details/8880012html
本文將做爲我《從零開始作OpenCL開發》系列文章的第一篇。程序員
1 異構計算、GPGPU與OpenCL編程
OpenCL是當前一個通用的由不少公司和組織共同發起的多CPU\GPU\其餘芯片 異構計算(heterogeneous)的標準,它是跨平臺的。旨在充分利用GPU強大的並行計算能力以及與CPU的協同工做,更高效的利用硬件高效的完成大規模的(尤爲是並行度高的)計算。在過去利用GPU對圖像渲染進行加速的技術很是成熟,可是咱們知道GPU的芯片結構擅長大規模的並行計算(PC級的GPU可能就是CPU的上萬倍),CPU則擅長邏輯控制,所以不僅侷限與圖像渲染,人們但願將這種計算能力擴展到更多領域,因此這也被稱爲GPGPU(即通用處計算處理的GPU)。數組
簡單的說,咱們的CPU並不適合計算,它是多指令單數據流(MISD)的體系結構,更加擅長的是作邏輯控制,而數據處理基本是單流水線的,因此咱們的代碼for(i=0;...;i++)這種在CPU上要重複迭代的跑不少遍,可是你的顯卡GPU則不是這樣,GPU是典型的單指令多數據(SIMD)的體系結構,它不擅長邏輯控制,可是確實天生的向量計算機器,對於for(i=0;...;i++)這樣的代碼有時只須要跑一遍,因此圖形世界中那麼多的頂點、片斷才能快速的並行在顯卡中渲染處理架構
GPU的晶體管能夠到幾十億個,而CPU一般只有幾個億,編程語言
如上圖是NVidia Femi100的結構,它有着大量的並行計算單元。分佈式
因此人們就想如何將更多的計算代碼搬到GPU上,讓他不知作rendering,而CPU只負責邏輯控制,這種一個CPU(控制單元)+幾個GPU(有時可能再加幾個CPU)(計算單元)的架構就是所謂的異構編程(heterogeneous),在這裏面的GPU就是GPGPU。異構編程的前景和效率是很是振奮人心的,在不少領域,尤爲是高並行度的計算中,效率提高的數量級不是幾倍,而是百倍千倍。wordpress
其實NVIDIA在很早就退出了利用其顯卡的GPGPU計算 CUDA架構,當時的影響是很大的,將不少計算工做(科學計算、圖像渲染、遊戲)的問題提升了幾個數量級的效率,記得那時NVIDIA來浙大介紹CUDA,演示了實時的ray tracing、大量剛體的互相碰撞等例子,仍是激動了一下的,CUDA如今好像已經發展到了5.0,並且是NVDIA主力推的通用計算架構,可是CUDA最大的侷限就是它只能使用N家本身的顯卡,對於廣大的A卡用戶鞭長莫及。OpenCL則在以後應運而生,它由極大主流芯片商、操做系統、軟件開發者、學術機構、中間件提供者等公司聯合發起,它最初由Apple提出發起標準,隨後Khronos Group成立工做組,協調這些公司共同維護這套通用的計算語言。Khronos Group聽起來比較熟悉吧,圖像繪製領域著名的軟硬件接口API規範著名的OpenGL也是這個組織維護的,其實他們還維護了不少多媒體領域的規範,可能也是相似於Open***起名的(因此剛聽到OpenCL的時候就在想它與OpenGl有啥關係),OpenCl沒有一個特定的SDK,Khronos Group只是指定標準(你能夠理解爲他們定義頭文件),而具體的implementation則是由不一樣參與公司來作,這樣你會發現NVDIA將OpenCL作了實現後即成到它的CUDA SDK中,而AMD則將其實現後放在所謂是AMD APP (Accelerated Paral Processing)SDK中,而Intel也作了實現,因此目前的主流CPU和GPU都支持OpenCL架構,雖然不一樣公司作了不一樣的SDK,可是他們都遵守一樣的OpenCL規範,也就是說原則上若是你用標準OpenCl頭中定義的那些接口的話,使用NVIDIA的SDK編的程序能夠跑在A家的顯卡上的。可是不一樣的SDK會有針對他們芯片的特定擴展,這點相似於標磚OpenGL庫和GL庫擴展的關係。函數
OpenGL的出現使得AMD在GPGPU領域終於迎頭遇上的NVIDIA,可是NVIDIA雖爲OpenCL的一員,可是他們彷佛更加看重本身的獨門武器CUDA,因此N家對OpenCL實現的擴展也要比AMD少,AMD因爲同時作CPU和GPU,還有他們的APU,彷佛對OpenCL更來勁一些。性能
2.關於在GPU上寫代碼的那些事兒
OpenCL也是經過在GPU上寫代碼來加速,只不過他把CPU、GPU、其餘什麼芯片給統一封裝了起來,更高了一層,對開發者也更友好。說到這裏忽然很想贅述一些在GPU上寫代碼的那些歷史。。
其實最開始顯卡是不存在的,最先的圖形處理是放在CPU上,後來發現能夠再主板上放一個單獨的芯片來加速圖形繪製,那時還叫圖像處理單元,直到NVIDIA把這東西作強作大,而且第一給它改了個NB的稱呼,叫作GPU,也叫圖像處理器,後來GPU就以比CPU高几倍的速度增加性能。
開始的時候GPU不能編程,也叫固定管線的,就是把數據按照固定的通路走完
和CPU一樣做爲計算處理器,瓜熟蒂落就出來了可編程的GPU,可是那時候想在GPU上編程可不是容易的事,你只能使用GPU彙編來寫GPU程序,GPU彙編?聽起來就是很高級的玩意兒,因此那時使用GPU繪製不少特殊效果的技能只掌握在少數圖形工程師身上,這種方式叫可編程管線。
很快這種桎桍被打破,GPU上的高級編程語言誕生,在當時更先進的一些顯卡上(記憶中應該是3代顯卡開始吧),像C同樣的高級語言可使程序員更加容易的往GPU寫代碼,這些語言表明有nvidia和微軟一塊兒創做的CG,微軟的HLSL,openGl的GLSL等等,如今它們也一般被稱爲高級着色語言(Shading Language),這些shader目前已經被普遍應用於咱們的各類遊戲中。
在使用shading language的過程當中,一些科研人員發現不少非圖形計算的問題(如數學、物理領域的並行計算)能夠假裝成圖形問題利用Shading Language實如今GPU上計算,而這結果是在CPU上跑速度的N倍,人們又有了新的想法,想着利用GPU這種性能去解決全部大量並行計算的問題(不僅圖形領域),這也叫作通用處理的GPU(GPGPU),不少人嘗試這樣作了,一段時間不少論文在寫怎樣怎樣利用GPU算了哪一個東東。。。可是這種工做都是假裝成圖形處理的形式作的,尚未一種自然的語言來讓咱們在GPU上作通用計算。這時又是NVIDIA帶來了革新,09年先後推出的GUDA架構,可讓開發者在他們的顯卡上用高級語言編寫通用計算程序,一時CUDA熱了起來,直到如今N卡都印着大大的CUDA logo,不過它的侷限就是硬件的限制。
OpenCL則突破了硬件的壁壘,試圖在全部支持的硬件上搭建起通用計算的協同平臺,無論你是cpu仍是gpu統統一視同仁,都能進行計算,能夠說OpenCL的意義在於模糊了主板上那兩種重要處理器的界限,並使在GPU上跑代碼變得更容易。
3 OpenCL架構
3.1 硬件層:
上面說的都是關於通用計算以及OpenCL是什麼,下面就提綱挈領的把OpenCL的架構總結一下:
如下是OpenCL硬件層的抽象
它是一個Host(控制處理單元,一般由一個CPU擔任)和一堆Computer Device(計算處理單元,一般由一些GPU、CPU其餘支持的芯片擔任),其中Compute Device切分紅不少Processing Element(這是獨立參與單數據計算的最小單元,這個不一樣硬件實現都不同,如GPU可能就是其中一個Processor,而CPU多是一個Core,我猜的。。由於這個實現對開發者是隱藏的),其中不少個Processing Element能夠組成組爲一個Computer Unit,一個Unit內的element之間能夠方便的共享memory,也只有一個Unit內的element能夠實現同步等操做。
3.2 內存架構
其中Host有本身的內存,而在compute Device上則比較複雜,首先有個常量內存,是全部人能用的,一般也是訪問最快的可是最稀少的,而後每一個element有本身的memory,這是private的,一個組內的element有他們共用的一個local memery。仔細分析,這是一個高效優雅的內存組織方式。數據能夠沿着Host-》gloabal-》local-》private的通道流動(這其中可能跨越了不少個硬件)。
3.3軟件層面的組成
這些在SDK中都有對應的數據類型
setup相關:
Device:對應一個硬件(標準中特別說明多core的CPU是一個整個Device)
Context:環境上下文,一個Context包含幾個device(單個Cpu或GPU),一個Context就是這些device的一個聯繫紐帶,只有在一個Context上的那些Device才能彼此交流工做,你的機器上能夠同時存在不少Context。你能夠用一個CPu建立context,也能夠用一個CPU和一個GPU建立一個。
Command queue:這是個給每一個Device提交的指令序列
內存相關:
Buffers:這個好理解,一塊內存
Images:畢竟並行計算大多數的應用前景在圖形圖像上,因此原生帶有幾個類型,表示各類維度的圖像。
gpu代碼執行相關:
Program:這是全部代碼的集合,可能包含Kernel是和其餘庫,OpenCl是一個動態編譯的語言,代碼編譯後生成一箇中間文件(可實現爲虛擬機代碼或者彙編代碼,看不一樣實現),在使用時鏈接進入程序讀入處理器。
Kernel:這是在element跑的核函數及其參數組和,若是把計算設備看作好多人同時爲你作一個事情,那麼Kernel就是他們每一個人作的那個事情,這個事情每一個人都是一樣的作,可是參數多是不一樣的,這就是所謂的單指令多數據體系。
WorkI tem:這就是表明硬件上的一個Processing Element,最基本的計算單元。
同步相關:
Events:在這樣一個分佈式計算的環境中,不一樣單元之間的同步是一個大問題,event是用來同步的
他們的關係以下圖
上面就是OpenCL的入門介紹,其實說實話在10年左右就跟蹤過GPGPU相關的東西,那時不少相關技術還存在於實驗室,後來的CUDA出現後,也激動過,學習過一陣,不過CUDA過分依賴於特定硬件,產業應用前景並很差,只能作作工程試驗,你總不能讓用戶裝個遊戲的同時,讓他順便換個高配的N卡吧。因此一度也對這個領域不太感興趣,最近看到OpenCL的出現,發現可能這個架構仍是有很好的應用前景的,也是衆多廠商目前協力力推的一個東西。想一想一下一個迭代10000次的for循環一遍過,仍是很激動的一件事。
在遊戲領域,OpenCL已經有了不少成功的實踐,好像EA的F1就已經應用了OpenCL,還有一些作海洋的lib應用OpenCL(海面水波的FFT運算在過去是很是慢的),另外還有的庫乾脆利用OpenCL去直接修改現有的C代碼,加速for循環等,甚至還有OpenCl版本的C++ STL,叫thrust,因此我以爲OpenCL可能會真正的給咱們帶來些什麼~
如下是一些關於OpenCL比較重要的資源:
http://www.khronos.org/opencl/ 組織的主頁
https://developer.nvidia.com/opencl N家的主頁
http://developer.amd.com/resources/heterogeneous-computing/opencl-zone/ A家的主頁
http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/ 標準的reference
http://developer.amd.com/wordpress/media/2012/10/opencl-1.2.pdf 必看 最新的1.2版本標準
http://www.khronos.org/assets/uploads/developers/library/overview/opencl-overview.pdf 必看,入門的review