OpenHMPP
OpenHMPP (HMPP[1] for Hybrid Multicore Parallel Programming) - programming standard for heterogeneous computing. Based on a set of compiler directives, standard is a programming model designed to handle hardware accelerators without the complexity associated with GPU programming. This approach based on directives has been implemented because they enable a loose relationship between an application code and the use of a hardware accelerator (HWA). IntroductionThe OpenHMPP directive-based programming model offers a syntax to offload computations on hardware accelerators and to optimize data movement to/from the hardware memory. The model is based on works initialized by CAPS (Compiler and Architecture for Embedded and Superscalar Processors), a common project from INRIA, CNRS, the University of Rennes 1 and the INSA of Rennes. OpenHMPP conceptOpenHMPP is based on the concept of codelets, functions that can be remotely executed on HWAs. The OpenHMPP codelet conceptA codelet has the following properties:
These properties ensure that a codelet RPC can be remotely executed by a HWA. This RPC and its associated data transfers can be asynchronous. Codelet RPCsHMPP provides synchronous and asynchronous RPC. Implementation of asynchronous operation is hardware dependent. HMPP Memory ModelHMPP considers two address spaces: the host processor one and the HWA memory. Directives conceptThe OpenHMPP directives may be seen as “meta-information” added in the application source code. They are safe meta-information i.e. they do not change the original code behavior. They address the remote execution (RPC) of a function as well as the transfers of data to/from the HWA memory. The table below introduces the OpenHMPP directives. OpenHMPP directives address different needs: some of them are dedicated to declarations and others are dedicated to the management of the execution.
Concept of set of directivesOne of the fundamental points of the HMPP approach is the concept of directives and their associated labels which makes it possible to expose a coherent structure on a whole set of directives disseminated in an application. There are two kinds of labels:
OpenHMPP Directives SyntaxIn order to simplify the notations, regular expressions will be used to describe the syntax of the HMPP directives. The color convention below is used for the description of syntax directives:
General syntaxThe general syntax of OpenHMPP directives is:
#pragma hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&]
!$hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&] Where:
Directive parametersThe parameters associated to a directive may be of different types. Below are the directive parameters defined in OpenHMPP:
OpenHMPP directivesDirectives for declaring and executing a codeletA
The syntax of the directive is: #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]*] More than one codelet directive can be added to a function in order to specify different uses or different execution contexts. However, there can be only one codelet directive for a given call site label. The The syntax of the directive is: #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]* An example is shown here : /* declaration of the codelet */
#pragma hmpp simple1 codelet, args[outv].io=inout, target=CUDA
static void matvec(int sn, int sm, float 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);
........
}
In some cases, a specific management of the data throughout the application is required (CPU/GPU data movements optimization, shared variables...). The #pragma hmpp <grp_label> group [, version = <major>.<minor>[.<micro>]?]? [, target = target_name[:target_name]*]]? [, cond = “expr”]? Data transfers directives to optimize communication overheadWhen using a HWA, the main bottleneck is often the data transfers between the HWA and the main processor.
The #pragma hmpp <grp_label> allocate [,args[arg_items].size={dimsize[,dimsize]*}]*
The #pragma hmpp <grp_label> release
The #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]
The #pragma hmpp <grp_label> [codelet_label]? delegatedstore ,args[arg_items] [,args[arg_items].addr="expr"]* [,args[arg_items].section={[subscript_triplet,]+}]*
The #pragma hmpp <grp_label> codelet_label synchronize
In the following example, the device initialization, memory allocation and upload of the input data are done only once outside the loop and not in each iteration of the loop. The int main(int argc, char **argv) {
#pragma hmpp sgemm allocate, args[vin1;vin2;vout].size={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
Sharing data between codeletsThose directives map together all the arguments sharing the given name for all the group. The types and dimensions of all mapped arguments must be identical. The #pragma hmpp <grp_label> map, args[arg_items] This directive is quite similar as the #pragma hmpp <grp_label> mapbyname [,variableName]+ Global variableThe The syntax of this directive is: #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]* The notation Acceleration of regionsA region is a merge of the codelet/callsite directives. The goal is to avoid code restructuration to build the codelet. Therefore, all the attributes available for In C language: #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 } ImplementationsThe OpenHMPP Open Standard is based on HMPP Version 2.3 (May 2009, CAPS entreprise). The OpenHMPP directive-based programming model is implemented in:
OpenHMPP is used by HPC actors[who?] in Oil & Gas,[citation needed] Energy,[citation needed] Manufacturing,[citation needed] Finance,[citation needed] Education & Research.[citation needed] See alsoReferences
|