HMPP開放標準

HMPP用於異構多核並行編程。
OpenHMPP標準基於一組指令，是用於處理硬件加速器的編程模型，但又沒有GPU編程的相關複雜性。這種基於指令的方法已經實現，因為他們使應用程序代碼和硬件加速器使用之間形成鬆散關係。
本文涉及組成OpenHMPP標準的HMPP指令, 但並不處理指令的執行鏈接到指令執行。

**簡介**
OpenHMPP基於指令的編程模型提供了一種語法，有效地減輕硬件加速器上的計算，優化數據向/從硬件存儲器移動。
模型基於  CAPS (編譯器和超標量體系結構以及嵌入式處理器)date=20110616053110  的初始化工作, 以及來自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。異步操作的執行依賴於硬件。
Synchronous versus asynchronous RPC

**HMPP 存儲器模型**
HMPP考慮到兩個地址空間: 一個主機處理器和硬件存儲器。
HMPPP memory Model

**指令概念**
OpenHMPP指令可能被視為“元信息” 添加到應用程序源代碼。它們是安全的元信息，即不會改變原始代碼的行為。它們處理函數的遠程執行(RPC)，以及數據向/從硬件存儲器傳輸。
下表介紹了OpenHMPP指令。OpenHMPP指令滿足不同需求: 其中一些專門用於聲明，其他用於執行的管理。

**指令集的概念**
HMPP方法的基本點之一是指令的概念及其關聯的標籤，使它能夠在分佈於應用程序中的整個指令集上公開一個相干結構。
有兩種類型的標籤:- 一類關聯到codelet。攜帶這種標籤的指令一般僅限於管理一個(在文檔 的其餘部分稱為stand-alone，以便從一組codelet中區分開)。- 一類關聯到一組codelets。這些標籤說明如下: ““, 其中“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* &
其中:
*: 是命名一組 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指令的版本。
*argsarg_items.size={dimsize,dimsize*}: 指定一個非標量參數 (數組)的大小。
*argsarg_items.io=inout: 表示指定函數參數是輸入, 輸出或兩者兼而有之。默認情況下, 非限定參數為輸入。
*cond = "expr": 指定組或codelets開始執行的一個條件C或Fortran布爾表達式的值為是 C或Fortran布爾表達式的值為true。
*target=target_name:target_name*: 指定是哪個target以嘗試使用給定的順序。
*asynchronous: 指定不阻止codelet的 執行 (默認是同步的)。
*args.advancedload=true: 表明指定的參數是預加載的。只有in或inout參數可以被預加載。
*argsarg_items.noupdate=true: 此屬性指定 硬件上的數據已經可用，因此不需要轉換。 當設置了此屬性時, 所考慮的參數沒有任何傳遞。
*args.addr="": 是一個表達式，給出了數據上載的地址。
*args.const=true: 表示參數只要上載一次。

**OpenHMPP 指令**

**聲明和執行一個codelet的指令**
codelet指令聲明在硬件加速器上遠程執行計算。
codelet 指令:- codelet標籤是強制性的並且在應用程序中是唯一的- 如果沒有組被定義則不需要組標籤。- Codelet指令在函數聲明之前插入。
該指令的語法是:
#pragma hmpp grp_label> codelet_label codelet 
, version = major.minor.micro??
, argsarg_items.io=inout                             , argsarg_items.size={dimsize,dimsize*}                             , argsarg_items.const=true                             , cond = "expr"
, target=target_name:target_name
可以在一個函數中加入多個codelet指令，以便指定不同用途或不同執行文本。但是, 一個給定調用站點標籤只能有一個codelet指令。
Callsite指令指定程序內的給定點如何使用一個codelet。
該指令的語法是:
#pragma hmpp grp_label> codelet_label callsite
, asynchronous?
, argsarg_items.size={dimsize,dimsize*}                      , argsarg_items.advancedload=false                      , argsarg_items.addr="expr"                      , argsarg_items.noupdate=true
這裡有一個例子:
/* declaration of the codelet */
#pragma hmpp simple1 codelet, argsoutv.io=inout, target=CUDA
static void matvec(int sn, int sm, loat invsm, float inmsnsm, float *outv){
int i, j;
for (i = 0 ; i 
group指令允許聲明一組codelets。 指令中定義的參數應用於所有屬於該組的 codelets。
該指令的語法是:
#pragma hmpp grp_label> group 
, version = ..?? 
, target = target_name:target_name*? 
, cond  = “expr”?

**數據傳輸指令可以優化通信開銷**
硬件使用時的主要瓶頸通常是硬件和住處理器之間的數據傳輸。
要限制通信開銷,可以通過使用硬件的異步屬性，連續執行相同的codelet以重疊數據傳輸。- allocate指令
allocate指令鎖定硬件，並分配所需的內存量。
#pragma hmpp grp_label> allocate ,argsarg_items.size={dimsize,dimsize*}- release指令
release指令指定何時為一組或一個獨立codelet釋放硬件。 
#pragma hmpp grp_label> release- advancedload 指令
advancedload指令在codelet遠程執行之前預取數據。
#pragma hmpp grp_label> codelet_label? advancedload
,argsarg_items
,argsarg_items.size={dimsize,dimsize*}                   ,argsarg_items.addr="expr"                   ,argsarg_items.section={subscript_triplet,+}                   ,asynchronous- delegatedstore 指令
delegatedstore指令是一個同步障，以等待一個異步codelet執行完成，然後下載結果。
#pragma hmpp grp_label> codelet_label? delegatedstore 
,argsarg_items
,argsarg_items.addr="expr"                 ,argsarg_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, argsvin1;vin2;vout.siez={size,size}
#pragma hmpp sgemm advancedload, argsvin1;vin2;vout, argsm,n,k,alpha,beta

for ( j = 0 ; j 
所有映射參數的類型和尺寸必須是相同的。
map指令映射設備上的幾個參數。
#pragma hmpp grp_label>  map, argsarg_items
此指令除了參數按其名稱直接指定映射之外，與map指令很類似。 mapbyname 指令相當於多映射指令。
#pragma hmpp grp_label> mapbyname ,variableName+

**全局變量**
Resident指令聲明某些變量在一個組內為全局變量。 然後可以從任何屬於組的codelet中直接訪問這些變量。此指令應用於源代碼中在其之後的聲明語句。
此指令的語法是:
#pragma hmpp grp_label> resident 
, args::var_name.io=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         
, argsarg_items.io=inout                            , cond = "expr", argsarg_items.const=true                            , target=target_name:target_name                            , argsarg_items.size={dimsize,dimsize*}                            , argsarg_items.advancedload=false                            , argsarg_items.addr="expr"                            , argsarg_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 Standarddate=20121007111624 -  How Hardware Will Shape Languagesdate=20120113021731  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 Portdate=20110720171956  By CEA (Commissariat à l'Energie Atomique et aux Energies Alternatives) for PRACE (Partnership for Advanced Computing in Europe)