OpenHMPP

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.

Introduksjon

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.

Konseptet med OpenHMPP-standarden

OpenHMPP-standarden er basert på begrepet codelet, som er en funksjon som kan utføres eksternt på maskinvare.

Konseptet med codelet

En kodelet har følgende egenskaper:

  1. Det er en ren funksjon.
    • Den inneholder ikke statiske eller flyktige variabeledeklarasjoner, og refererer ikke til globale variabler, bortsett fra variabler erklært som " resident" i et OpenHMPP-direktiv.
    • den inneholder ikke anrop til funksjoner med ikke-synlig innhold (det vil si at den ikke kan være integrert). Dette inkluderer bruk av biblioteker og systemfunksjoner som malloc, printf ...
    • Hvert anrop til funksjonen må referere til en ren statisk funksjon (ingen funksjonspekere).
  2. Den returnerer ingen verdi (ekvivalenten i C er en ugyldig funksjon; ekvivalenten i FORTRAN er en subrutine).
  3. Antall argumenter må være faste (ingen vararg som i C).
  4. Det er ikke rekursivt.
  5. Disse parametrene antas ikke å være alias (i pekerforstand).
  6. Den inneholder ikke direktiver callsite(det vil si ingen RPC-anrop til en annen kodelet) eller andre HMPP-direktiver.

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.

RPC-utførelse av et kodelet

OpenHMPP gir en synkron og asynkron protokoll for ekstern prosedyreanrop .

Den asynkrone operasjonsimplementeringen er maskinvareavhengig.

Minnemodellen implementert

OpenHMPP tar hensyn til to adresserom:

HMPP-retningslinjer

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.

HMPP-retningslinjer
Instruksjoner for flytkontroll Retningslinjer for datahåndtering
Uttalelser kodelet gruppe bosatt kart mapbyname
Operative direktiver anropssynkroniser region alloker release advancedload delegatedstore

Retningslinjer satt konsept

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:

Syntaks av OpenHMPP-direktiver

For å forenkle notasjoner, vil vanlige uttrykk brukes til å beskrive syntaksen til OpenHMPP-direktiver.

Følgende fargekonvensjoner vil også bli brukt:

Generell syntaks

Den generelle syntaksen for OpenHMPP-direktiver er:

  • For C-språket:
#pragma hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&]
  • For FORTRAN-språket:
!$hmpp <grp_label> [codelet_label]? directive_type [,directive_parameters]* [&]

eller:

  • <grp_label>er en unik identifikator som representerer en gruppe kodeletter. Hvis ingen grupper er definert i applikasjonen, kan denne etiketten være fraværende. For å være gyldig må etikettnavnet følge denne grammatikken [a-z,A-Z,_][a-z,A-Z,0-9,_]*. Merk at både tegn <og >tilhører syntaksen og kreves i denne merkesammenheng;
  • codelet_labeler en unik identifikator som navngir et kodelet. For å være gyldig må navnet på etiketten følge følgende grammatikk:[a-z,A-Z,_][a-z,A-Z,0-9,_]*
  • directive er navnet på direktivet;
  • directive_parametersangir parametrene som er knyttet til direktivet. Disse parametrene kan være av forskjellige typer og spesifisere enten argumenter sendt til direktivet eller en kjøringsmodus (asynkron eller synkron for eksempel);
  • [&] er et tegn som brukes til å indikere at direktivet fortsetter på neste linje (samme for C og FORTRAN).
Direktivparametere

Parametrene knyttet til et direktiv kan ha flere typer.

For å følge parametrene som er definert med OpenHMPP:

  • version = major.minor[.micro]: spesifiserer versjonen av HMPP-direktivene som er tatt i betraktning av forprosessoren;
  • args[arg_items].size={dimsize[,dimsize]*}: spesifiserer størrelsen på ikke-skalære parametere (en matrise);
  • args[arg_items].io=[in|out|inout]: angir statusen til argumentene til den spesifiserte funksjonen (input, output eller begge deler). Ukvalifiserte argumenter er som standard innganger;
  • cond = "expr": spesifiserer en betingelse for utførelsen, i form av et boolsk C- eller FORTRAN-uttrykk som må være sant for at utførelsen av gruppen eller kodelet skal begynne;
  • target=target_name[:target_name]*: spesifiserer listen over mål du vil prøve å bruke, rekkefølgen på utseendet er rekkefølgen for å sjekke tilgjengeligheten;
  • asynchronous: spesifiserer at utførelsen av kodelet ikke blokkerer (som standard synkron);
  • args[<arg_items>].advancedload=true: indikerer at de angitte parametrene er forhåndslastet. Bare parametere med inn- eller ut-status kan forhåndslastes;
  • args[arg_items].noupdate=true: spesifiserer at dataene allerede er tilgjengelige på utstyret og at overføring derfor ikke er nødvendig. Når denne eiendommen er satt, blir det ikke overført det vurderte argumentet;
  • args[<arg_items>].addr="<expr>": er et uttrykk som eksplisitt gir adressen til dataene;
  • args[<arg_items>].const=true: indikerer at argumentet må lastes ned en gang og bare én gang.

OpenHMPP-direktiver

Erklæring og utførelse av et kodelet

Et direktiv codeletspesifiserer at en versjon av følgende funksjon skal optimaliseres for en spesifisert maskinvare.

For direktivet codelet :

  • Kodeletiketten er obligatorisk og må være unik i applikasjonen.
  • Gruppetiketten er ikke obligatorisk hvis ingen gruppe er definert.
  • Direktivet må settes inn umiddelbart før erklæringen om den aktuelle funksjonen.

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]?

Direktiv anvendt på dataoverføring (optimalisering av merkostnader knyttet til kommunikasjon)

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.

  • "alloker" -direktivet

Den låser maskinvaren og tildeler den nødvendige mengden minne.

#pragma hmpp <grp_label> allocate [,args[arg_items].size={dimsize[,dimsize]*}]*
  • "slipp" -direktivet

Den spesifiserer når materialet skal frigjøres for en gruppe eller for en frittstående kodelet.

#pragma hmpp <grp_label> release
  • "advancedload" -direktivet

Den laster dataene før ekstern kjøring av kodelet.

#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" -direktivet

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.

#pragma hmpp <grp_label> [codelet_label]? delegatedstore ,args[arg_items] [,args[arg_items].addr="expr"]* [,args[arg_items].section={[subscript_triplet,]+}]*
  • Asynkrone beregninger

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:

#pragma hmpp <grp_label> codelet_label synchronize
  • Eksempel

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

Datadeling mellom kodeletter

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]+

Global variabel

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.

Region akselerasjon

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 }

Implementeringer

OpenHMPP er basert på versjon 2.3 av HMPP (Mai 2009, CAPS-selskap).

Modellen foreslått av OpenHMPP er implementert av:

  • CAPS Compilers, kompilatorene levert av CAPS Entreprise for hybrid databehandling
  • PathScale ENZO Compiler Suite (NVIDIA GPU-støtte)

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.

Se også

Referanser