HMPP開放標準
此條目沒有列出任何參考或來源。 (2011年1月20日) |
HMPP用於異構多核並行編程。
OpenHMPP標準基於一組指令,是用於處理硬件加速器的編程模型,但又沒有GPU編程的相關複雜性。這種基於指令的方法已經實現,因為他們使應用程序代碼和硬件加速器使用之間形成鬆散關係。
本文涉及組成OpenHMPP標準的HMPP指令, 但並不處理指令的執行鏈接到指令執行。
簡介
OpenHMPP基於指令的編程模型提供了一種語法,有效地減輕硬件加速器上的計算,優化數據向/從硬件存儲器移動。
模型基於 CAPS (編譯器和超標量體系結構以及嵌入式處理器)(頁面存檔備份,存於網際網路檔案館) 的初始化工作, 以及來自INRIA, CNRS, 雷恩第一大學和雷恩INSA的共同項目。
OpenHMPP標準概念
OpenHMPP標準基於codelets的概念, 可以在硬件上遠程執行。
OpenHMPP Codelet 概念
codelet具有以下屬性:
- 它是一個純函數。
- 它不包含靜態或不穩定的變量聲明,也不涉及任何全局變量,除非這些已經由HMPP 「resident」指令所聲明
- 它不包含任何具有無形體(不能內聯)的函數調用。這包含庫和系統函數的使用, 例如 malloc, printf, ...
- 每個函數必須引用靜態純函數(沒有函數指針)。
- 它不返回任何值(C中的void函數或FORTRAN子程序)。
- 參數的數量應該是固定的(即沒有像C中的vararg那樣可變數量的參數)。
- 它不是遞歸的。
- 它的參數設定為non-aliased。
- 它不包含callsite指令(即RPC至另一個codelet)或其他HMPP指令。
這些屬性確保codelet RPC可以通過硬件遠程執行。此RPC及其相關的數據傳輸可以是異步的。
Codelet RPCs
HMPP提供同步和異步的RPC。異步操作的執行依賴於硬件。
![](http://images.weserv.nl/?url=//upload.wikimedia.org/wikipedia/commons/thumb/0/0d/HMPP_RPC.png/390px-HMPP_RPC.png)
HMPP 存儲器模型
HMPP考慮到兩個地址空間: 一個主機處理器和硬件存儲器。
![](http://images.weserv.nl/?url=//upload.wikimedia.org/wikipedia/commons/thumb/6/6b/HMPP_Memory_Model.png/370px-HMPP_Memory_Model.png)
指令概念
OpenHMPP指令可能被視為「元信息」 添加到應用程序源代碼。它們是安全的元信息,即不會改變原始代碼的行為。它們處理函數的遠程執行(RPC),以及數據向/從硬件存儲器傳輸。
下表介紹了OpenHMPP指令。OpenHMPP指令滿足不同需求: 其中一些專門用於聲明,其他用於執行的管理。
流程控制指令 | 數據管理標籤 | |
聲明 | codelet group |
resident map mapbyname |
操作標籤 | callsite synchronize region |
allocate release advancedload delegatedstore |
指令集的概念
HMPP方法的基本點之一是指令的概念及其關聯的標籤,使它能夠在分布於應用程序中的整個指令集上公開一個相干結構。
有兩種類型的標籤:
- 一類關聯到codelet。攜帶這種標籤的指令一般僅限於管理一個(在文檔 的其餘部分稱為stand-alone,以便從一組codelet中區分開)。
- 一類關聯到一組codelets。這些標籤說明如下: 「<LabelOfGroup>「, 其中「LabelOfGroup」 是由用戶指定一個名稱。 具有這種標籤的指令一般涉及到整個組。組的概念是保留給這樣一類問題,即要求對整個應用程序的數據做具體管理以獲取性能。
OpenHMPP指令語法
為了簡化符號, 正則表達式 將用於描述HMPP指令的語法。 下面的顏色通常用於描述指令的語法:
- 保留的HMPP關鍵字是藍色;
- 在HMPP關鍵字中可以被減少的基本語法是紅色;
- 用戶變量仍然為黑色。
一般語法
OpenHMPP指令的一般語法如下:
- C語言:
#pragma hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&]
- FORTRAN語言:
!$hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&]
其中:
<grp_label>
: 是命名一組 codelets 的唯一標識符。在應用程序中沒有組被定義的情況下, 這個標籤可以簡單地略過。Legal標籤必須遵循此語法: [a-z,A-Z,_][a-z,A-Z,0-9,_]*。請注意 「< >」 字符屬於語法,且對這類標籤是強制性的。codelet_label
: 是命名一個codelet的唯一標識符。Legal 標籤必須遵循此語法: [a-z,A-Z,_][a-z,A-Z,0-9,_]*directive
: 是指令的名稱;directive_parameters
: 指定一些指令相關聯的參數。這些參數可能是不同類型並指定 給指令的某些參數或執行的一種模式(例如同步與異步);[&]
: 是用於在下一行繼續該指令的字符 (C和FORTRAN都是相同的)。
指令參數
關聯到一個指令的參數可能是不同類型。以下是 在HMPP中定義的指令參數:
version = major.minor[.micro]
: 由預處理器指定HMPP指令的版本。args[arg_items].size={dimsize[,dimsize]*}
: 指定一個非標量參數 (數組)的大小。args[arg_items].io=[in|out|inout]
: 表示指定函數參數是輸入, 輸出或兩者兼而有之。默認情況下, 非限定參數為輸入。cond = "expr"
: 指定組或codelets開始執行的一個條件C或Fortran布爾表達式的值為是 C或Fortran布爾表達式的值為true。target=target_name[:target_name]*
: 指定是哪個target以嘗試使用給定的順序。asynchronous
: 指定不阻止codelet的 執行 (默認是同步的)。args[<arg_items>].advancedload=true
: 表明指定的參數是預加載的。只有in或inout參數可以被預加載。args[arg_items].noupdate=true
: 此屬性指定 硬件上的數據已經可用,因此不需要轉換。 當設置了此屬性時, 所考慮的參數沒有任何傳遞。args[<arg_items>].addr="<expr>"
:<expr>
是一個表達式,給出了數據上載的地址。args[<arg_items>].const=true
: 表示參數只要上載一次。
OpenHMPP 指令
聲明和執行一個codelet的指令
codelet指令聲明在硬件加速器上遠程執行計算。
codelet 指令:
- codelet標籤是強制性的並且在應用程序中是唯一的
- 如果沒有組被定義則不需要組標籤。
- Codelet指令在函數聲明之前插入。
該指令的語法是:
#pragma hmpp <grp_label> codelet_label codelet [, version = major.minor[.micro]?]? [, args[arg_items].io=[[in|out|inout]]* [, args[arg_items].size={dimsize[,dimsize]*}]* [, args[arg_items].const=true]* [, cond = "expr"] [, target=target_name[:target_name]*]
可以在一個函數中加入多個codelet指令,以便指定不同用途或不同執行文本。但是, 一個給定調用站點標籤只能有一個codelet指令。
Callsite指令指定程序內的給定點如何使用一個codelet。
該指令的語法是:
#pragma hmpp <grp_label> codelet_label callsite [, asynchronous]? [, args[arg_items].size={dimsize[,dimsize]*}]* [, args[arg_items].advancedload=[[true|false]]* [, args[arg_items].addr="expr"]* [, args[arg_items].noupdate=true]*
這裡有一個例子:
/* declaration of the codelet */
#pragma hmpp simple1 codelet, args[outv].io=inout, target=CUDA static void matvec(int sn, int sm, loat inv[sm], float inm[sn][sm], float *outv){ int i, j; for (i = 0 ; i < sm ; i++) { float temp = outv[i]; for (j = 0 ; j < sn ; j++) { temp += inv[j] * inm[i][ j]; } outv[i] = temp; } int main(int argc, char **argv) { int n; ........ /* codelet use */ #pragma hmpp simple1 callsite, args[outv].size={n} matvec(n, m, myinc, inm, myoutv); ........ }
某些情況下, 需要具體管理整個應用程序的數據(CPU/GPU 數據移動優化, 共享變量...)。
group指令允許聲明一組codelets。 指令中定義的參數應用於所有屬於該組的 codelets。
該指令的語法是:
#pragma hmpp <grp_label> group [, version = <major>.<minor>[.<micro>]?]? [, target = target_name[:target_name]*]]? [, cond = “expr”]?
數據傳輸指令可以優化通信開銷
硬件使用時的主要瓶頸通常是硬件和住處理器之間的數據傳輸。
要限制通信開銷,可以通過使用硬件的異步屬性,連續執行相同的codelet以重疊數據傳輸。
- allocate指令
allocate指令鎖定硬件,並分配所需的內存量。 #pragma hmpp <grp_label> allocate [,args[arg_items].size={dimsize[,dimsize]*}]*
- release指令
release指令指定何時為一組或一個獨立codelet釋放硬件。
#pragma hmpp <grp_label> release
- advancedload 指令
advancedload指令在codelet遠程執行之前預取數據。 #pragma hmpp <grp_label> [codelet_label]? advancedload
,args[arg_items] [,args[arg_items].size={dimsize[,dimsize]*}]* [,args[arg_items].addr="expr"]* [,args[arg_items].section={[subscript_triplet,]+}]* [,asynchronous]
- delegatedstore 指令
delegatedstore指令是一個同步障,以等待一個異步codelet執行完成,然後下載結果。 #pragma hmpp <grp_label> [codelet_label]? delegatedstore
,args[arg_items] [,args[arg_items].addr="expr"]* [,args[arg_items].section={[subscript_triplet,]+}]*
- 異步計算
同步指令指定等待,直到一個異步callsite執行完成。對於同步指令, codelet 標籤始終是強制性的,並且若是codelet屬於一個組,需要有組標籤。 #pragma hmpp <grp_label> codelet_label synchronize
- 示例
在下面的例子中,完成設備初始化,內存分配和輸入數據的上載在循環外只有一次,而不是每次循環迭代。
同步指令允許在啟動另一個迭代之前等待codelet的異步執行的完成。最後在循環外delegatedstore指令將上載sgemm結果。
int main(int argc, char **argv) {
#pragma hmpp sgemm allocate, args[vin1;vin2;vout].siez={size,size} #pragma hmpp sgemm advancedload, args[vin1;vin2;vout], args[m,n,k,alpha,beta] for ( j = 0 ; j < 2 ; j ++) { #pragma hmpp sgemm callsite, asynchronous, args[vin1;vin2;vout].advancedload=true, args[m,n,k,alpha,beta].advancedload=true sgemm (size, size, size, alpha, vin1, vin2, beta, vout); #pragma hmpp sgemm synchronize } #pragma hmpp sgemm delegatedstore, args[vout] #pragma hmpp sgemm release
Codelets之間共享數據
這些指令共同映射所有參數共享所有組的給定名稱。
所有映射參數的類型和尺寸必須是相同的。
map指令映射設備上的幾個參數。
#pragma hmpp <grp_label> map, args[arg_items]
此指令除了參數按其名稱直接指定映射之外,與map指令很類似。 mapbyname 指令相當於多映射指令。
#pragma hmpp <grp_label> mapbyname [,variableName]+
全局變量
Resident指令聲明某些變量在一個組內為全局變量。 然後可以從任何屬於組的codelet中直接訪問這些變量。此指令應用於源代碼中在其之後的聲明語句。
此指令的語法是:
#pragma hmpp <grp_label> resident [, args[::var_name].io=[[in|out|inout]]* [, args[::var_name].size={dimsize[,dimsize]*}]* [, args[::var_name].addr="expr"]* [, args[::var_name].const=true]*
符號::var_name 以::為前綴, 表示一個應用程序的變量聲明為resident。
加速區
codelet/callsite指令合併為一個區域。目的是避免代碼重構中構建codelet。 因此,所有codelet或callsite指令可用屬性都可以用於regions指令。 在C語言中:
#pragma hmpp [<MyGroup>] [label] region [, args[arg_items].io=[[in|out|inout]]* [, cond = "expr"]< [, args[arg_items].const=true]* [, target=target_name[:target_name]*] [, args[arg_items].size={dimsize[,dimsize]*}]* [, args[arg_items].advancedload=[[true|false]]* [, args[arg_items].addr="expr"]* [, args[arg_items].noupdate=true]* [, asynchronous]? [, private=[arg_items]]* { C BLOCK STATEMENTS }
實現
HMPP開放標準基於HMPP 2.3版本(2009年5月, CAPS 公司).
HMPP基於指令的編程模型已經實現如下:
- HMPP 工作檯, 用於混合計算的CAPS企業編譯器
- PathScale ENZO 編譯器套件(支持NVIDIA GPUs)
此外,HMPP開放標準用於石油和天然氣,能源,製造業,金融,教育及研究領域的高性能計算,讓開發人員使用大部分多核處理器,同時保留其遺留資源。
參閱
參考
- OpenHMPP Website
- HMPP: A Hybrid Multi-core Parallel Programming Environment
- CAPS Entreprise SAS and PathScale, LLC to Jointly Collaborate on Making HMPP a New Open Standard(頁面存檔備份,存於網際網路檔案館)
- How Hardware Will Shape Languages(頁面存檔備份,存於網際網路檔案館) By David Chisnall
- Code acceleration with HMPP By ICHEC (Irish Center for High-End Computing)
- Expérience de programmation avec HMPP By IRMA (Institut de Recherche Mathématique Avancée) - FORTRAN examples
- Directive-based Heterogeneous Programming - A GPU-Accelerated RTM Use Case By TOTAL Technical and Scientific Center and CAPS Entreprise
- HMPP Port(頁面存檔備份,存於網際網路檔案館) By CEA (Commissariat à l'Energie Atomique et aux Energies Alternatives) for PRACE (Partnership for Advanced Computing in Europe)