1. 簡(jiǎn)介
OpenCL(Open Computing Language)立宜,即開放運(yùn)算語言,是一個(gè)統(tǒng)一的開放式的開發(fā)平臺(tái)薯酝。OpenCL是首個(gè)提出的并行開發(fā)的開放式的扔嵌、兼容的、免費(fèi)的標(biāo)準(zhǔn),它的目的是為異構(gòu)系統(tǒng)通用提供統(tǒng)一開發(fā)平臺(tái)。OpenCL最初是由蘋果公司設(shè)想和開發(fā),并在與AMD灾馒,IBM,英特爾和NVIDIA技術(shù)團(tuán)隊(duì)的合作之下初步完善遣总。隨后睬罗,蘋果將這一草案提交至Khronos Group轨功。
2.框架組成
OpenCL的框架組成可以劃分為三個(gè)部分,分別為OpenCL平臺(tái)API傅物、OpenCL運(yùn)行時(shí)API夯辖,以及OpenCL內(nèi)核編程語言。
2.1 平臺(tái)API
平臺(tái)(Platform)這個(gè)詞在OpenCL中擁有非常特定的含義董饰,它表示的是宿主機(jī)蒿褂、OpenCL設(shè)備和OpenCL框架的組合。多個(gè)OpenCL平臺(tái)可以共存于一臺(tái)異構(gòu)計(jì)算機(jī)卒暂。舉個(gè)例子啄栓,CPU開發(fā)人員和GPU開發(fā)人員可以在同一個(gè)系統(tǒng)上分別定義自己的OpenCL框架。這時(shí)就需要一種方法來查詢系統(tǒng)中可用的OpenCL 框架也祠,哪些OpenCL設(shè)備是可用的昙楚,以及這些OpenCL設(shè)備的特性。相當(dāng)于CUDA的主機(jī)和設(shè)備之間的關(guān)系诈嘿。
此外堪旧,為了形成一個(gè)給定的OpenCL應(yīng)用平臺(tái),還需要對(duì)這些框架和設(shè)備所屬的子集進(jìn)行控制奖亚。這些功能都是由OpenCL平臺(tái)API中的函數(shù)來解決的淳梦。此外,平臺(tái)API還提供了為OpenCL創(chuàng)建上下文的函數(shù)昔字。OpenCL的上下文規(guī)定了OpenCL應(yīng)用程序的打開方式(相當(dāng)是CUDA中核函數(shù)的調(diào)用)爆袍,這可以在宿主機(jī)程序代碼中得到驗(yàn)證。
2.2 運(yùn)行時(shí)API
平臺(tái)API提供函數(shù)創(chuàng)建好上下文之后作郭,運(yùn)行時(shí)API主要提供使用上下文提供的功能滿足各種應(yīng)用需求的函數(shù)陨囊。這是一個(gè)規(guī)模龐大且內(nèi)容十分復(fù)雜的函數(shù)集。運(yùn)行時(shí)API的第一個(gè)任務(wù)是創(chuàng)建一個(gè)命令隊(duì)列夹攒。命令隊(duì)列與設(shè)備相關(guān)聯(lián)蜘醋,而且一個(gè)上下文中可以同時(shí)存在多個(gè)活動(dòng)的命令隊(duì)列。有了命令隊(duì)列咏尝,就可以通過調(diào)用運(yùn)行時(shí)API提供的函數(shù)來進(jìn)行內(nèi)存對(duì)象的定義以及管理內(nèi)存中的對(duì)象所依賴的所有其他對(duì)象堂湖。以上是內(nèi)存對(duì)象的持有操作,另外還有釋放操作状土,也是由運(yùn)行時(shí)API提供的。
此外伺糠,運(yùn)行時(shí)API還提供了創(chuàng)建動(dòng)態(tài)庫(kù)所需要的程序?qū)ο蟮暮瘮?shù)蒙谓,正是這些動(dòng)態(tài)庫(kù)實(shí)現(xiàn)了Kernel的定義。最后训桶,運(yùn)行時(shí)層的函數(shù)會(huì)發(fā)出與命令隊(duì)列交互的命令累驮。此外酣倾,管理數(shù)據(jù)共享和對(duì)內(nèi)核的執(zhí)行加以限制同步點(diǎn)也是由運(yùn)行時(shí)API處理的。
2.3 內(nèi)核編程語言
內(nèi)核編程語言是用于編寫OpenCL內(nèi)核代碼的谤专。除了宿主機(jī)程序之外躁锡,內(nèi)核程序也十分重要,它負(fù)責(zé)完成OpenCL中的實(shí)際工作置侍。在部分OpenCL實(shí)現(xiàn)中用戶可以跟其他語言編寫的原生內(nèi)核實(shí)現(xiàn)交互映之,但多數(shù)情況下內(nèi)核是需要用戶使用內(nèi)核編程語言編寫實(shí)現(xiàn)的。OpenCL C編程語言就是OpenCL中的內(nèi)核編程語言蜡坊,該編程語言是"ISO C99 標(biāo)準(zhǔn)"的一個(gè)擴(kuò)展子集杠输,也就是說它是由 ISO C99語言派生而來的。現(xiàn)在的OpenCL2.1還支持C++秕衙,是基于eISO/IEC JTC1 SC22 WG21 N 3690(C++14)蠢甲。
2.4 適合平臺(tái)
1)AMD
根據(jù)AMD官網(wǎng)所提供的內(nèi)容,OpenCL在AMD顯卡中只能適用X86核心的CPU架構(gòu)据忘,而對(duì)其他PowerPC和ARM架構(gòu)則不適用鹦牛;并且也不是所有的AMD顯卡都能運(yùn)行OpenCL,按其官網(wǎng)介紹只能是AMD Radeon勇吊、AMD FirePro和AMD Firestream三種類型的顯卡曼追;但對(duì)于操作系統(tǒng)則可以是Linux或Windows的系統(tǒng)。
2)NVIDIA
NVIDIA OpenCL是一種運(yùn)行于具有CUDA能力GPU上的一種底層API萧福,即OpenCL是運(yùn)行于CUDA之上的一種API拉鹃,從而若適用CUDA的平臺(tái),也同樣適用OpenCL鲫忍。根據(jù)NVIDIA官網(wǎng)最新版本的CUDA 7.5適合的平臺(tái)膏燕。
3.計(jì)算架構(gòu)
OpenCL 的設(shè)計(jì)目標(biāo)是為開發(fā)人員提供一套移植性強(qiáng)且高效運(yùn)行的解決方案。為了更好的描述OpenCL設(shè)計(jì)的核心理念悟民,Khronos Group官方將OpenCL的計(jì)算架構(gòu)分解成四個(gè)模型坝辫,分別平臺(tái)模型(Platform Model)、內(nèi)存模型(Memory Model)射亏、執(zhí)行模型(Execution Model)以及編程模型(Programming Model)近忙。
3.1 平臺(tái)模型(Platform Model)
從整體上來看,主機(jī)(host)端是負(fù)責(zé)掌管整個(gè)運(yùn)算的所有計(jì)算資源智润,因此OpenCL 應(yīng)用程序首先是由主機(jī)端開始及舍,然后由程序?qū)⒏鱾€(gè)計(jì)算命令從主機(jī)端發(fā)送給每個(gè) GPU 設(shè)備處理單元,運(yùn)行完畢之后最后由主機(jī)端結(jié)束窟绷。
從圖中可以直觀的看到锯玛,最基本處理單位是Processing Element,簡(jiǎn)稱PE(處理單元),而一個(gè)或多個(gè)PE組成了Compute Unit攘残,簡(jiǎn)稱CU(計(jì)算單元)拙友,進(jìn)而一個(gè)或多個(gè)CU就組成了Compute Device,即OpenCL設(shè)備歼郭。最后遗契,一個(gè)或多個(gè)OpenCL設(shè)備連接到主機(jī),并等待著處理主機(jī)發(fā)送的計(jì)算指令病曾,由于PE是最基本處理單位牍蜂,因此每條計(jì)算指令最終都?xì)wPE進(jìn)行處理,而PE是在CU中的知态。
3.2 內(nèi)存模型(Memory Model)
OpenCL將內(nèi)核程序中用到的內(nèi)存分為圖示的四種不同的類型捷兰。
其中它們的讀寫特性分別為:
- Global memory:工作區(qū)內(nèi)的所有工作節(jié)點(diǎn)都可以自由的讀寫其中的任何數(shù)據(jù)。OpenCL C語言提供了全局緩存(Global buffer)的內(nèi)建函數(shù)负敏。
- Constant memory: 工作區(qū)內(nèi)的所有工作節(jié)點(diǎn)可以讀取其中的任何數(shù)據(jù)但不可以對(duì)數(shù)據(jù)內(nèi)容進(jìn)行更改贡茅,在內(nèi)核程序的執(zhí)行過程中保持不變。主機(jī)端負(fù)責(zé)分配和初始化常量緩存(Constant buffer)其做。
- Local memory: 只有同一工作組中的工作節(jié)點(diǎn)才可以對(duì)該類內(nèi)存進(jìn)行讀寫操作顶考。它既可以為 OpenCL 的執(zhí)行分配一塊私有內(nèi)存空間,也可以直接將其映射到一塊全局緩存(Global buffer)上妖泄。特點(diǎn)是運(yùn)行速度快驹沿。
- Private memory: 只有當(dāng)前的工作節(jié)點(diǎn)能對(duì)該內(nèi)存進(jìn)行訪問和讀寫操作。一個(gè)工作節(jié)點(diǎn)內(nèi)部的私有緩存(Private buffer)對(duì)其他節(jié)點(diǎn)來說是不可見的蹈胡。
3.3 執(zhí)行模型(Execution Model)
OpenCL的執(zhí)行模型是應(yīng)用程序通過主機(jī)端對(duì)OpenCL設(shè)備端上的內(nèi)核程序進(jìn)行管理渊季,該模型分為兩個(gè)模塊:一個(gè)是在主機(jī)端執(zhí)行的管理程序,也稱為Hostprogram罚渐,另一個(gè)是主機(jī)端的Hostprogram所管理的在OpenCL上執(zhí)行的程序却汉,也被稱作Kernels。在執(zhí)行Kernels前荷并,先要建立一個(gè)索引空間合砂,來對(duì)設(shè)備里的每個(gè)節(jié)點(diǎn)進(jìn)行標(biāo)識(shí),每個(gè)節(jié)點(diǎn)都將執(zhí)行相同的kernel程序源织。在每個(gè)工作組中翩伪,都有一個(gè)局部ID,每個(gè)節(jié)點(diǎn)在全局里還有個(gè)全局 ID谈息,OpenCL使用NDRange來定義這個(gè)索引空間缘屹。
如圖示的OpenCL執(zhí)行模型,其過程可以細(xì)分為如下的步驟完成:
- 查詢連接主機(jī)上的OpenCL設(shè)備侠仇;
- 創(chuàng)建一個(gè)關(guān)聯(lián)到OpenCL設(shè)備的context囊颅;
- 在關(guān)聯(lián)的設(shè)備上創(chuàng)建可執(zhí)行程序;
- 從程序池中選擇kernel程序;
- 從主機(jī)或設(shè)備上創(chuàng)建存儲(chǔ)單元踢代;
- 如果需要將主機(jī)的數(shù)據(jù)復(fù)制到OpenCL設(shè)備上的存儲(chǔ)單元上;
- 執(zhí)行kernel程序執(zhí)行嗅骄;
- 從OpenCL設(shè)備上復(fù)制結(jié)果到主機(jī)上
3.4 編程模型(Programming Model)
OpenCL支持兩種編程模型胳挎,分別為數(shù)據(jù)并行編程模型和任務(wù)并行編程模型,并支持上面由這兩種編程模型混合的混合編程模型溺森。
數(shù)據(jù)并行編程模型
OpenCL提供一個(gè)分層的數(shù)據(jù)并行編程模型慕爬,即典型的SIMD計(jì)算模型,其特點(diǎn)是每個(gè)數(shù)據(jù)經(jīng)由同樣的指令序列處理屏积,而處理數(shù)據(jù)的次序是不確定的医窿,并且每個(gè)數(shù)據(jù)的處理是不相干的,即任一線程的計(jì)算不得依賴于其它線程的結(jié)果(包括中間結(jié)果)炊林。任務(wù)并行編程模型
任務(wù)并行模型中的每個(gè)內(nèi)核是在一個(gè)獨(dú)立的索引空間中執(zhí)行的姥卢,也就是說,執(zhí)行內(nèi)核的計(jì)算機(jī)單元內(nèi)只有一個(gè)工作組渣聚,其中只有一個(gè)工作項(xiàng)独榴。在這樣的模型中,每個(gè)線程都可以執(zhí)行不同的帶啊奕枝,著相當(dāng)于MIMD的計(jì)算模型棺榔,適合多核心CPU。