OpenHMPP Open Standard (HMPP står for Hybrid Multicore Parallel Programming ) er en retningslinjebasert programmeringsmodell designet for å manipulere maskinvareakseleratorer uten å bekymre seg for kompleksiteten forbundet med GPU- programmering . Valget av implementering for denne modellen falt på direktiver fordi de tillater et løst forhold mellom applikasjonskoden og bruken av maskinvareakseleratorer .
NB : Denne artikkelen dekker OpenHMPP-direktivene som utgjør Open Standard, men tar ikke for seg gjennomføring av direktiver knyttet til implementering av direktiver.
Syntaksen som tilbys av OpenHMPP-modellen gjør det mulig å distribuere beregningene på maskinvareakseleratorene effektivt og optimalisere bevegelsene til data fra / til maskinvarens minne.
Modellen er basert på CAPS (Compiler and Architecture for Embedded and Superscalar Processors) prosjektet utført i fellesskap av INRIA, CNRS, University of Rennes 1 og INSA of Rennes.
OpenHMPP-standarden er basert på begrepet codelet, som er en funksjon som kan utføres eksternt på maskinvare.
En kodelet har følgende egenskaper:
Disse egenskapene sikrer at en RPC-kodelet kan kjøres eksternt av maskinvare. Denne RPC-samtalen og tilhørende dataoverføringer kan være asynkrone.
OpenHMPP gir en synkron og asynkron protokoll for ekstern prosedyreanrop .
Den asynkrone operasjonsimplementeringen er maskinvareavhengig.
OpenHMPP tar hensyn til to adresserom:
OpenHMPP-direktiver kan sees på som "metainformasjon" som legges til kildekoden til applikasjonen. Det er derfor ufarlig metainformasjon, det vil si at den ikke endrer kodens opprinnelige oppførsel.
De adresserer den eksterne kjøringen (RPC) av funksjonen, samt dataoverføringene fra / til maskinvareminnet. Følgende tabell introduserer OpenHMPP-direktivene, klassifisert etter behovet: noen er dedikert til erklæringer, andre er dedikert til kjøringsledelse.
Instruksjoner for flytkontroll | Retningslinjer for datahåndtering | |
---|---|---|
Uttalelser | kodelet gruppe | bosatt kart mapbyname |
Operative direktiver | anropssynkroniser region | alloker release advancedload delegatedstore |
Et av de grunnleggende punktene i tilnærmingen som er foreslått av OpenHMPP-modellen er begrepet direktiver assosiert med merkelapper som gjør det mulig å sette opp en sammenhengende struktur for et helt sett med direktiver, formidlet i applikasjonen.
Det er to typer etiketter:
For å forenkle notasjoner, vil vanlige uttrykk brukes til å beskrive syntaksen til OpenHMPP-direktiver.
Følgende fargekonvensjoner vil også bli brukt:
Den generelle syntaksen for OpenHMPP-direktiver er:
eller:
Parametrene knyttet til et direktiv kan ha flere typer.
For å følge parametrene som er definert med OpenHMPP:
Et direktiv codeletspesifiserer at en versjon av følgende funksjon skal optimaliseres for en spesifisert maskinvare.
For direktivet codelet :
Syntaksen til direktivet er:
#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]*]Det er mulig å ha flere direktiver codeletfor en gitt funksjon, hver spesifiserer forskjellige bruksområder eller forskjellige utførelsessammenhenger. Imidlertid kan det bare være ett direktiv callsitefor en codeletgitt etikett .
Direktivet callsitespesifiserer bruken av et kodelet på et gitt punkt i programmet.
Syntaksen til direktivet er:
#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]*Et eksempel å følge:
/* déclaration du 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; ........ /* Utilisation du codelet */ #pragma hmpp simple1 callsite, args[outv].size={n} matvec(n, m, myinc, inm, myoutv); ........ }I noen tilfeller er spesifikk datahåndtering nødvendig i applikasjonen (optimalisering av databevegelser mellom CPU og GPU, delte variabler osv.).
Direktivet grouptillater erklæring av en gruppe kodeletter. Parametrene som er definert for dette direktivet, brukes på alle kodeletter tilknyttet denne gruppen.
Syntaksen til direktivet er:
#pragma hmpp <grp_label> group [, version = <major>.<minor>[.<micro>]?]? [, target = target_name[:target_name]*]? [, cond = “expr”]?Hovedflaskehalsen når du bruker HWA er ofte dataoverføringer mellom maskinvaren og hovedprosessoren.
For å begrense merkostnadene knyttet til kommunikasjon, kan dataoverføringene være vanlig for påfølgende kjøringer av samme kodelet ved bruk av den asynkrone egenskapen til utstyret.
Den låser maskinvaren og tildeler den nødvendige mengden minne.
#pragma hmpp <grp_label> allocate [,args[arg_items].size={dimsize[,dimsize]*}]*Den spesifiserer når materialet skal frigjøres for en gruppe eller for en frittstående kodelet.
#pragma hmpp <grp_label> releaseDen laster dataene før ekstern kjøring av kodelet.
Den utgjør en synkron barriere som gjør det mulig å vente på fullførelsen av utførelsen av en asynkron kodelet, før resultatene lastes ned.
Direktivet synchronizespesifiserer at du må vente på asynkron kjøring av callsite.
For dette direktivet er kodeletmerke alltid obligatorisk, og merket groupkreves hvis kodelet er tilknyttet en gruppe. Syntaksen til direktivet er:
I det følgende eksemplet utføres maskinvareinitialisering, minnetildeling og nedlasting av inngangsdata en gang, utenfor sløyfen i stedet for å utføres på hver iterasjon av sløyfen.
Direktivet synchronizelar deg vente på slutten av den asynkrone kjøringen av kodelet før du starter en ny iterasjon. Endelig delegatedstorelaster direktivet , plassert utenfor sløyfen, utdataene fra "sgemm".
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
Disse direktivene gjør det mulig å dele alle argumentene med samme navn for en hel gruppe.
Typene og dimensjonene til alle delte argumenter må være de samme.
Direktivet maptillater å knytte flere argumenter på maskinvaren.
#pragma hmpp <grp_label> map, args[arg_items]Direktivet mapbynameligner på direktivet, mapbortsett fra at argumentene som skal kartlegges, spesifiseres direkte etter navn. Direktivet mapbynametilsvarer flere direktiver map.
Notasjonen er som følger:
#pragma hmpp <grp_label> mapbyname [,variableName]+Direktivet residenterklærer variabler som globale i en gruppe.
Disse variablene kan nås direkte fra hvilken som helst kodelet i gruppen på maskinvaren (de betraktes på en måte som "hjemmehørende" på maskinvaren).
Dette direktivet gjelder erklæringen som følger den i kildekoden.
Syntaksen til dette direktivet er:
#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]*Notasjonen ::var_name, med prefikset ::, indikerer en applikasjonsvariabel erklært som resident.
En region er en blanding av kodelet / callite-direktivene. Målet er å unngå restrukturering av koden pålagt ved eksplisitt opprettelse av kodeletter. Derfor kan alle attributter som er tilgjengelige for direktiver codeleteller callsitebrukes til direktivet region.
Syntaksen er som følger:
#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 }OpenHMPP er basert på versjon 2.3 av HMPP (Mai 2009, CAPS-selskap).
Modellen foreslått av OpenHMPP er implementert av:
I tillegg brukes OpenHMPP innenfor rammen av HPC- prosjekter utført innen felt som petroleum, energi, industri, utdanning og forskning, og gjør det mulig å utvikle høyytelsesversjoner av applikasjonene sine, samtidig som koden som allerede er produsert, bevares.