GPU程式設計--OpenCL四大模型
本篇結構:
- 前言
- 平臺模型
- 執行模型
- 記憶體模型
- 程式設計模型
- 參考資料
一、前言
“模型”是對現實世界的一個抽象,它對現實世界的進行簡化,把不關心的,或者不影響所關注部分的內容,都從模型去掉。模型有助於理解它反映的那部分世界的規律。
OPenCL作為開放性的異構計算的標準,支援的平臺有CPU、GPU、DSP、FPGA等。為了把各個廠家、各個平臺的各種概念和術語都統一到一個標準的環境下,OpenCL定義了若干個模型。這對於OpenCL這種本來就定義在異構平臺的標準尤其重要,通過這些模型,可以使用相同的語言/語義來描述不同環境下的平行計算。
OpenCL定義了平臺模型(Platform Model)、執行模型(Execution Model)、記憶體模型(Memory Model)、程式設計模型(Programming Model)。
二、平臺模型
不同廠商的OpenCL實施定義了不同的OpenCL平臺,通過OpenCL平臺,主機能夠和OpenCL裝置之間進行互動操作。
OpenCL使用了一種InstallableClient Driver模型,這樣不同廠商的平臺就能夠在系統中共存(例如:在一個系統中可以既有AMD的平臺和Intel的平臺)。現在的OpenCL driver模型不允許不同廠商的GPU同時執行。
OpenCL平臺需要包含一個主處理器和一個或多個OpenCL裝置。平臺模型定義了host和device的角色,並且為device提供了一種抽象的硬體模型。一個device可以被劃分成一個或多個計算單元,這些計算單元在之後能被分成一個或多個“處理單元”(processing elements)。
host負責管理所有的OpenCL裝置,宿主機發起計算任務,選擇特定的OpenCL裝置並建立計算環境,在AMD和Nvida的OpenCL平臺中,一般都指x86 CPU。device主要負責資料運算操作,宿主機將計算任務和資料傳送給OPenCL裝置。裝置呼叫內部計算單元進行計算,完成後將結果返還給宿主機,該次計算任務結束。
平臺模型是應用開發的重點,其保證了OpenCL程式碼的可移植性(在具有OpenCL能力的系統間)。平臺模型的API允許一個OpenCL應用能夠適應和選擇對應的平臺和計算裝置,從而在相應平臺和裝置上執行應用。
應用可以使用OpenCL執行時API,選擇對應提供商提供的對應平臺。不過,平臺上能指定和互動的裝置,也只限於供應商提供的那些裝置。例如,如果選擇了A公司的平臺,那麼就不能使用B公司的GPU。不過,平臺硬體並不需要由供應商獨家提供。例如,AMD和Intel的實現可以使用其他公司的x86 CPU作為裝置。
編寫OpenCL C程式碼時,裝置架構會被抽象成平臺模型。供應商只需要將抽象的架構對映到對應的物理硬體上即可。平臺模型定義了具有一組計算單元的裝置,且每個計算單元的功能都是獨立的。計算單元也可以劃分成更多個處理單元。舉個例子,AMD Radeon R9 290X圖形卡(device)包含44個向量處理器(計算單元)。每個計算單元都由4個16通道SIMD引擎,一共就有64個SIMD通道(處理單元)。Radeon R9 290X上每個SIMD通道都能處理一個標量指令。執行GPU裝置能同時執行44x16x4=2816條指令。
三、執行模型
一個OpenCL應用由兩個不同部分組成:一個宿主機程式(host program)以及一個或多個核心(kernel)組成的集合。宿主機程式在宿主機上執行,核心在OpenCL裝置上執行,它們共同完成OpenCL應用的具體工作。
OpenCL是一個主從處理模型,根本是宿主機如何利用OpenCL裝置上大量的計算資源進行有效計算。所以OpenCL執行模型的任務就是如何高效地呼叫這些計算資源。
- 宿主機將每一個處理單元(PE)分配一個索引號,這個唯一的索引號稱為全域性ID(Global ID),全體PE被看做一個工作空間的work-item。
- 因為可能需要處理陣列、圖形乃至三維影象,所以對應的工作空間也可以定義為一維、二維、三維。
- 為了更好的處理不同的資料,可以將工作空間進行粗粒度的劃分,如將一部分ID劃分到一組,這個組稱為work-group,每一個組內也可以分配ID,不過這個ID稱為區域性ID(Local ID)。全域性ID和區域性ID存在對映關係。
- OpenCL規範中使用一個長度為N的整數陣列來描述工作空間的大小(N<=3),稱為NDRange。陣列中的數值對應相應維度上工作點的個數。eg {2, 3}表示一個維度上工作項為2,另一個維度為3。
- 如果將我們常見的三維魔方想象成一個工作空間,那麼一維即某種顏色(eg:紅色)的一行,即一維個數為3,二維為相應的那個面,二維個數為9,三維即為整個工作空間,三維個數為27。
如果想更詳細瞭解執行模型NDRange等相關內容,可以參看OpenCL程式設計指南,有詳細的插圖,講解很細緻。
3.1、上下文
計算工作主要在OpenCL裝置上進行,但宿主機也扮演著非常重要的角色,核心就是在宿主機上定義的。宿主機主要通過上下文(Context)管理OpenCL裝置,對核心的正確執行進行協調和記憶體管理。
那什麼是上下文?
上下文是一個軟硬體資源整合,它定義了一個環境,核心就在這個環境中定義和執行。由以下資源定義上下文:
- 裝置:OpenCL程式呼叫的計算裝置
- 核心:在計算裝置上執行的並行程式
- 程式物件:核心程式的原始碼(.cl檔案)和可執行檔案
- 記憶體物件:計算裝置執行OpenCL程式所需的變數
上下文由宿主機使用API進行建立、管理、銷燬。
3.2、命令佇列
主機與OpenCL裝置之間的互動是通過命令完成的,根據計算量的大小,計算裝置並不能立刻執行完被分配的計算任務。那麼宿主機只能等著計算裝置把任務計算完了才能繼續分配新的任務麼?不是這樣的,每一個計算裝置都會有一個命令佇列。命令佇列只能管理一個計算裝置。
命令佇列由宿主機建立,並在定義上下文之後關聯到一個OpenCL裝置。宿主機將命令放入命令佇列,然後排程這些命令在關聯裝置上執行。
OpenCL支援3種型別的命令:
- 核心執行命令(kernel execution command):在OpenCL裝置的處理單元上執行核心。
- 記憶體命令(memory command):在宿主機與記憶體裝置之間移動資料,或者在兩者之間進行記憶體對映。
- 同步命令(synchronization command):對命令執行的順序施加約束。
- 亂序執行: 命令按照在命令佇列中的順序進行發射,但不保證計算裝置是按照這個順序進行執行的。
- 有序執行: 命令按照在命令佇列中的順序進行發射和執行,上一條命令執行完成後才能發射下一條命令。
宿主機程式可以為一個計算裝置建立多個命令佇列—一個計算裝置可以有多個命令佇列。這些命令佇列沒有關聯。這也就意味著一個計算裝置可以執行多個種類的任務。
四、記憶體模型
一般而言,不同的平臺之間有不同的儲存系統。例如,CPU有快取記憶體而GPU就沒有。為了程式的可移植性,OpenCL定義了抽象的記憶體模型,程式實現的時候只需關注抽象的記憶體模型,具體向硬體上的對映由驅動來完成。
與通用計算程式的記憶體物件相似,OpenCL將裝置中的儲存器抽象成四層結構的儲存模型:
- 宿主機記憶體(host memory):這個記憶體區域只對宿主機可見。
- 全域性記憶體(global memory):這個儲存區域允許讀、寫所有工作組中的所有工作項。工作項可以讀、寫全域性記憶體中一個記憶體物件的任何元素。讀、寫全域性記憶體可能會快取,這取決於裝置的容量。
- 常量記憶體(constant memory):全域性記憶體中的一塊區域,在核心的執行過程中保持不變。宿主機負責對此中記憶體物件的分配和初始化。
- 區域性記憶體(local memory):隸屬於一個工作組的記憶體區域。它可以用來分配一些變數,這些變數由此工作組中的所有工作項共享。在OpenCL裝置上,可能會將其實現成一塊專有的記憶體區域,也可能將其對映到全域性記憶體中。
- 私有記憶體(private memory):這個記憶體區域是一個工作項私有的區域。一個工作項私有記憶體中定義的變數對其他工作項不可見。
在程式執行期間,需要宿主機和計算裝置進行資料交換,存在兩種方式:
- 顯式地複製資料:將需要的資料拷貝到工作組空間,計算完成後再拷貝出去(傳形參)。
- 記憶體對映:將需要計算資料的地址傳進去(傳指標)。
五、程式設計模型
OpenCL執行模型定義了一個OpenCL應用如何對映到處理單元、記憶體區域和宿主機。這是一個“以硬體為中心”的模型。現在換個角度,介紹如何使用程式設計模型將並行演算法對映到OpenCL。
OpenCL定義了兩種不同的程式設計模型:任務並行和資料並行。
- 資料並行:將需要計算的資料進行等分,分配給不同的計算裝置進行計算。如需要進行兩個很大矩陣的求和運算,那麼就可以將矩陣資料分成幾份,那麼理論上計算事件縮減為原來的1/N。這適用與資料想關聯不大的計算任務。
- 任務並行:如計算資料量不大,但每一個步驟前後依賴,如你必須先將水燒開才能下面條,如果你需要不斷的煮麵條,那麼就可以將這個過程分成階段,用好幾個鍋同時進行。
六、參考資料
OpenCL 2.0 異構計算
OpenCL程式設計指南
http://coderdock.com/categories/OpenCL/
相關文章
- cuda程式設計與gpu平行計算(四):cuda程式設計模型程式設計GPU模型
- GPU程式設計--CPU和GPU的設計區別GPU程式設計
- GPU程式設計(五):利用好sharedmemoryGPU程式設計
- GPU程式設計(五): 利用好shared memoryGPU程式設計
- Socket程式設計模型程式設計模型
- 程式設計基礎四大件程式設計
- Spark 程式設計模型(上)Spark程式設計模型
- GPU高效能程式設計CUDA實戰(二)GPU程式設計
- Java中神經網路Triton GPU程式設計Java神經網路GPU程式設計
- GPU程式設計(四):並行規約優化GPU程式設計並行優化
- MapReduce 程式設計模型 & WordCount 示例程式設計模型
- 併發程式設計---JMM模型程式設計模型
- Nio程式設計模型總結程式設計模型
- 網路程式設計-OSI模型程式設計模型
- mapreduce的程式設計模型,計數器程式設計模型
- GPU程式設計(零):老黃和他的核彈們GPU程式設計
- GPU精粹與Shader程式設計(四):真實感渲染GPU程式設計
- 併發程式設計模型小結程式設計模型
- 網路程式設計之IO模型程式設計模型
- 系統程式設計 - I/O模型程式設計模型
- 非同步程式設計模型的思考非同步程式設計模型
- Java網路程式設計和NIO詳解3:IO模型與Java網路程式設計模型Java程式設計模型
- cuda程式設計與gpu平行計算(六):圖稀疏矩陣轉為CSR結構並傳入gpu程式設計GPU矩陣
- GPU程式設計(一):Ubuntu下的CUDA8.0環境搭建GPU程式設計Ubuntu
- GPU精粹與Shader程式設計(一):關於基礎物理渲染GPU程式設計
- Linux網路程式設計之IO模型Linux程式設計模型
- WebGL程式設計指南(7)層次模型Web程式設計模型
- 網路程式設計-Netty-Reactor模型程式設計NettyReact模型
- 併發程式設計——IO模型詳解程式設計模型
- 程式設計模型(正規化)小結程式設計模型
- 10倍程式設計師的思考模型程式設計師模型
- SAP Cloud Application Programming 程式設計模型(CAP)的設計準則CloudAPP程式設計模型
- Javascript中常見的非同步程式設計模型JavaScript非同步程式設計模型
- 伺服器端程式設計之 IO 模型伺服器程式設計模型
- 序列模型第一週程式設計練習模型程式設計
- NVIDIA CUDA 程式設計模型之Grid和Block程式設計模型BloC
- SAP ABAP 平臺新的程式設計模型程式設計模型
- 四大遊戲程式設計網站,邊玩遊戲,邊學Python,拒絕枯燥快樂程式設計遊戲程式設計網站Python