讀書筆記-OpenCL編程指南 簡介

OpenCL是Open Computing Language(開放語言的縮寫)。設立OpenCL的目的就是爲日益龐大的並行計算市場提供一個開放的、免費的行業標準。它讓開發人員能夠利用CPU、GPU等計算設備內部巨大的並行計算能力。爲了保證通用計算,OpenCL在五個方面進行了規定:

  1. 系統調用全部的硬件資源
  2. 將C語言作爲並行程序模型的基礎,加快OpenCL程序的研發速度以及保證可移植性
  3. 做到與現有軟件體系結構通用
  4. 實現硬件平臺上的通用
  5. 提供承前啓後,向前兼容的通用支持

OpenCL 1.1語言

OpenCL通過公佈硬件來提供高度的可移植性,而不是將硬件隱藏在精巧的抽象之下。這說明OpenCL程序員必須顯式地定義平臺、上下文,以及在不同設備上調度工作。並不是所有程序員都需要OpenCL提供的詳細控制。沒關係,如果可以做其他選擇,高層模型往往是更好的方法。不過,即使是高層編程模型,也需要一個牢固(且可移植)的基礎,OpenCL就可以作爲這個基礎。

兩個並行程序設計模型:任務並行和數據並行

在數據並行程序設計模型中,程序員從可以併發更新的數據元素集合角度來考慮問題。並行性表述爲將相同的指令流併發地應用到各個數據元素,並行性體現在數據中。
在這裏插入圖片描述
在任務並行程序設計模型中,程序員直接定義和處理併發任務。問題分解爲可以併發運行的任務,然後再映射到一個並行計算機的處理單元(Prossing Element,PE)來執行。如果任務是獨立的,使用這個模型最爲容易,不過這個O型也可以用於共享數據的任務。如果要利用一組任務來計算,只有當最後一個任務完成時這個計算纔算完成。因爲任務的計算需求差別很大,合理地分佈使它們能夠在大致相同的時間完成可能很困難,這是一個負載平衡的問題。
在這裏插入圖片描述
作爲通用的編程框架OpenCL,同時支持這兩種模型。

OpenCL概念基礎

面向異構平臺的應用都必須完成以下步驟:
在這裏插入圖片描述
這些步驟通過OpenCL中的一系列API加上一個面向kernel的編程環境來完成。我們將採用一種分而治之的策略解釋以上步驟的所有攻擊。將問題分解爲以下模型:
在這裏插入圖片描述

平臺模型

在這裏插入圖片描述

執行模型

內核

OpenCL應用由兩個不同部分組成:一個宿主機程序以及一個或多個內核組成的集合。內核中OpenCL設備上執行。它們完成OpenCL應用的具體工作。內核通常是一些簡單的函數,將輸入內存對象轉換爲輸出內存對象。OpenCL定義了兩類內核:
在這裏插入圖片描述
內核如何在OpenCL設備上執行
內核在宿主機上定義。宿主機程序發出一個命令,提交內核在一個OpenCL設備上執行。由宿主機發出這個命令時,OpenCL運行時系統會創建一個整數索引空間對應這個索引空間中的各個點將分別執行內核的一個實例。將執行內核的各個實例稱爲一個工作項(work-item)。工作項由它在索引空間中的座標來標識。這些座標就是工作項的全局ID。
提交內核執行的命令相應地會創建一個工作項集合,其中各個工作項使用內核定義的同樣的指令序列。儘管指令序列是相同的,但是由於代碼中的分支語句或者通過全局ID選擇的數據可能不同,因此各個工作項的行爲可能不同。

工作項組織爲工作組work-group。工作組提供了對索引空間更粗粒度的分解,跨越整個全局索引。工作組在相應維度的大小相同,這個大小可以整除各維度中的全局大小。爲工作組指定一個唯一的ID,這個ID與工作項使用的索引空間有相同的維度。另外爲工作項指定一個局部ID,這個局部ID在工作組中是唯一的,這樣就能由其全局ID或者由其局部ID和工作組ID唯一地標識一個工作項。

我的理解------------------------------------------------------------------------------------------------------------
內核 注:下面的類比以一維作爲潛臺詞
工作項(work-item):執行內核的各個實例 --------> 內核相當於kernel類,內核的實例相當於kernel類實例化的對象,工作項就相當於這些對象
內核的各個實例對應於索引空間的各個點 --------> 索引空間相當於vector<kernel>,而各個點就是kernel類實例化的對象
工作項由它在索引空間中的座標來標識,這些座標就是工作項的全局ID --------> 索引空間中的座標相當於vector<kernel>中的索引
命令
工作項:內核定義的相同的指令序列 --------> 宿主機代碼提交的命令隊列相當於queue<command>類。工作項相當於queue<command>類實例化的對象,也就是命令隊列
工作集合:工作集合是一組相同的工作項的集合 --------> 工作集合相當於命令隊列的數組,即vector<queue<command>>

內核 命令隊列
工作項 kernel queue<command>
工作項集合 vector<kernel> vector<queue<command>>

內核實例和命令隊列實例對應情況:

執行者 kernel_instance_1 kernel_instance_2 kernel_instance_N
操作指令 queue<command>_instance_1 queue<command>_instance_2 queue<command>_instance_N

工作組的意思就是依據一個維度對工作項進行分組。用工作組指定一個唯一ID,替代工作組所擁有工作項在全局索引空間中原來的ID。給工作組中的工作項指定局部ID,這樣就可以通過工作組ID+局部ID索引到相應的工作項(工作組中的索引空間稱爲局部索引空間)。這樣就方便了對擁有多個處理單元的計算單元分配任務,也就是工作組中的每個工作項對應計算單元中的一個處理單元。依據上面所述的模型,OpenCL只能保證一個工作組中的工作項併發執行,並不會保證各個工作組之間會併發執行。

索引空間是一個N維的值網格,因此也稱爲NDRange。目前這個N維索引空間中的N可以是1,2,3。在一個OpenCL程序中,NDRange由一個長度爲N的整數數組定義,N指定索引空間各維度的大小。各個工作項的全局和局部ID都是一個N維元祖。

考慮一個2維的NDRange,使用小寫字母g表示給定下標x或y時各維度中一個工作項的全局ID。大寫字母G指示索引空間各維度的大小。各工作項在全局NDRange索引空間中有一個座標(gx,gy),全局索引空間的大小爲(Gx,Gy),工作項座標取值範圍爲[0, (Gx -1), 0 , (Gy-1)]。第一維工作項的數量爲Gx,第二維工作項的數量爲Gy。

小寫字母w表示工作組ID,大寫字母W表示各個維度中工作組的個數。局部索引空間中各個維度的工作項數量用大寫字母L表示,工作組中局部ID使用小寫字母l表示。大小爲GxGy的NDRange索引空間將劃分爲WxWy空間上的工作組,其索引爲(wx,wy)。各個工作組的大小爲Lx*Ly。
在這裏插入圖片描述
在這裏插入圖片描述
其中
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

關於工作項的分組:如果分組第一維包含m個工作項,第二維包含n個工作項,而索引空間是2維分別包含N和R個工作項,那麼N%m == 0 且 R%n ==0。比如索引空間的兩個維度有4個、8個工作項,分組包含各個維度2個工作項,整個也就是4個工作項。各個維度都可以整除。總共可以分配成8個工作組。

上下文

上下文定義一個環節,內核就在這個環境中定義和執行。由一下資源定義上下文:
在這裏插入圖片描述
程序對象包含內核的代碼,可以類比爲動態庫,可以從中取出內核使用的函數。

我的理解---------------------------------------------------------------------------------------------

OpenCL概念 –> 編程語言概念
platfrom –> 計算機
Context –> 操作系統
OpenCL device –> 虛擬機
kernel –>
program object –> 類中的方法
memory object –> 類中的數據成員

命令隊列

宿主機與OpenCL設備之間的交互是通過命令完成的。這些命令由宿主機提交給命令隊列。這些命令會在命令隊列中等待,直到在OpenCL設備上執行。命令隊列由宿主機創建,並在定義上下文之後關聯到一個OpenCL設備。宿主機將命令隊列,然後調度這些命令在關聯設備上執行。
在這裏插入圖片描述
在這裏插入圖片描述
命令總是與宿主機程序異步執行。宿主機程序向命令隊列提交命令,然後繼續工作,而不必等待命令完成。如果有必要讓宿主機等待一個命令,可以利用一個同步命令顯式建立約束。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

內存模型

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
大多數情況下,宿主機和OpenCL設備內存模型是獨立的。內存之間的交互有兩種方式:顯式複製數據或映射和解映射內存對象的內存區域。
在這裏插入圖片描述
當涉及併發時,內存就會成爲競爭對象,這是內存一致性問題。

在這裏插入圖片描述
在這裏插入圖片描述

編程模型

使用編程模型將並行算法映射到OpenCL:任務並行和數據並行,以及包含數據並行的任務。

數據並行編程模型

將一個邏輯指令序列併發地應用到數據結構上。關鍵是執行一個內核時定義的NDRange,算法設計者要保證問題中的數據結構與NDRange索引空間一致,將它們映射到OpenCL內存對象內核定義了OpenCL計算中作爲工作項併發應用的指令序列
在更復雜的數據並行問題中,一個工作組中的工作項需要共享數據。這要通過存儲在局部內存區域中的數據來支持。只要工作項之間引入了依賴性,就必須特別當心,不論工作項以什麼順序完成,都要生成相同的結果。換句話,工作項的執行需要同步。一個工作組中的工作項可能參與一個工作組柵欄。一個工作組中的所有工作項必須先先執行這個柵欄,之後才允許跨過這個柵欄繼續執行。工作組中執行內核的所有工作項都遇到工作組柵欄,或者都不會遇到這個柵欄。對於執行一個內核時不同工作組的工作項之間如何同步,OpenCL 1.1並未提供任何機制
OpenCL提供了層次結構的數據並行性工作組中的工作項的數據並行再加上工作組層次的數據並行。OpenCL規範討論了這種數據並行形式的兩個變種。在顯式模式(explicit model)中,程序員負責顯式地定義工作組的大小。利用第二個模型,即隱式模型(implicit model),程序員只需定義NDRange空間,由系統選擇工作組。

任務並行編程模型

OpenCL執行模型被設計爲以數據並行作爲主要目標。不過這個模型還支持大量任務並行算法
OpenCL將任務定義爲單個工作項執行的內核,而不考慮OpenCL應用中其他內核使用的NDRange。如果程序員所希望的併發性來自於任務,就會使用這個模型。例如,併發性可能只是通過矢量類型上的矢量操作來表述。或者任務可能使用原生內核接口定義的一個內核,並行性使用OpenCL之外的一個編程環境來表述。
任務並行的另一個版本就是內核作爲任務提交,利用一個亂序隊列同時執行這些任務。比如,在一個四核CPU上,一個核可能是宿主機,另外3個核配置爲一個OpenCL設備中的計算單元。OpenCL應用可以將所有6個任務入隊,由計算單元動態調度工作,以達到負載平衡用時最短的效果。
任務並行的第三個版本是使用OpenCL的事件模型連接到一個任務圖。提交到時間隊列的命令有可能生成事件。後續的命令在執行之前可能等待這些事件。與支持亂序執行模型的命令隊列結合使用,就允許OpenCL程序員在OpenCL中定義靜態任務圖,圖中的節點表示任務,邊爲節點之間的依賴(由事件管理)。

其他編程模型

在這裏插入圖片描述

難點:事件+內存一致性+kernel編程

API

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章