1. Introduktion

Det här dokumentet anger en samling kompilatordirektiv, biblioteksfunktioner och miljövariabler som du kan använda för att ange parallellitet med delat minne i C- och C++-program. De funktioner som beskrivs i det här dokumentet kallas gemensamt för OpenMP C/C++ Application Program Interface (API). Målet med den här specifikationen är att tillhandahålla en modell för parallell programmering som gör att ett program kan vara portabelt mellan arkitekturer med delat minne från olika leverantörer. Kompilatorer från många leverantörer har stöd för OpenMP C/C++-API:et. Mer information om OpenMP, inklusive OpenMP Fortran Application Program Interface, finns på följande webbplats:

https://www.openmp.org

Med de direktiv, biblioteksfunktioner och miljövariabler som definieras i det här dokumentet kan du skapa och hantera parallella program samtidigt som du tillåter portabilitet. Direktiven utökar C- och C++-sekventiella programmeringsmodellen med SPMD-konstruktioner (single program multiple data), arbetsdelningskonstruktioner och synkroniseringskonstruktioner. De stöder också delning och privatisering av data. Kompilatorer som stöder OpenMP C- och C++-API:et innehåller ett kommandoradsalternativ till kompilatorn som aktiverar och tillåter tolkning av alla OpenMP-kompilatordirektiv.

1.1 Omfång

Den här specifikationen omfattar endast användarriktad parallellisering, där du uttryckligen definierar vilka åtgärder kompilatorn och körningssystemet vidtar för att köra programmet parallellt. OpenMP C- och C++-implementeringar krävs inte för att söka efter beroenden, konflikter, dödlägen, konkurrensförhållanden eller andra problem som resulterar i felaktig programkörning. Du ansvarar för att säkerställa att programmet med hjälp av OpenMP C- och C++ API-konstruktionerna körs korrekt. Kompilatorgenererad automatisk parallellisering och direktiv till kompilatorn för att underlätta sådan parallellisering omfattas inte i det här dokumentet.

1.2 Definition av villkor

Följande termer används i det här dokumentet:

  • barriär

    En synkroniseringspunkt som alla trådar i ett team måste nå. Varje tråd väntar tills alla trådar i teamet anländer vid denna punkt. Det finns uttryckliga hinder som identifieras genom direktiv och implicita hinder som skapats genom genomförandet.

  • konstruera

    En konstruktion är ett påstående. Det består av ett direktiv, följt av ett strukturerat block. Vissa direktiv ingår inte i en konstruktion. (Se openmp-directive i bilaga C).

  • direktiv

    C eller C++ #pragma följt av identifieraren omp , annan text och en ny rad. Direktivet anger programmets beteende.

  • dynamisk omfattning

    Alla instruktioner i lexikal omfattning, plus alla instruktioner i en funktion som körs som ett resultat av utförandet av instruktioner i lexikal omfattning. En dynamisk omfattning kallas också för en region.

  • lexikal omfattning

    Påståenden som finns lexikalt inom ett strukturerat block.

  • huvudtråd

    Tråden som skapar ett team när en parallell region anges.

  • parallell region

    Instruktioner som är associerade med parallella OpenMP-konstruktioner och kan utföras av flera trådar.

  • privat

    En privat variabel namnger ett lagringsblock som är unikt för den tråd som gör referensen. Det finns flera sätt att ange att en variabel är privat: en definition inom en parallell region, ett threadprivate direktiv, en private, firstprivate, lastprivateeller reduction -sats eller användning av variabeln som en for loopkontrollvariabel i en for loop direkt efter ett for eller parallel for ett direktiv.

  • region

    En dynamisk omfattning.

  • Seriell område

    Instruktioner som endast körs av huvudtråden utanför den dynamiska omfattningen för en parallell region.

  • Serialisera

    Så här kör du en parallell konstruktion med:

    • ett team med trådar som endast består av en enda tråd (som är huvudtråden för den parallella konstruktionen),

    • seriell körningsordning för uttalanden i det strukturerade blocket (samma ordning som om blocket inte vore en del av en parallell konstruktion) och

    • ingen effekt på det värde som returneras av omp_in_parallel() (förutom effekterna av kapslade parallella konstruktioner).

  • delad

    En delad variabel namnger ett enda lagringsblock. Alla trådar i ett team som har åtkomst till den här variabeln har också åtkomst till det här enda lagringsblocket.

  • strukturerat block

    Ett strukturerat block är en instruktion (enkel eller sammansatt) med en enda ingång och en enda utgång. Om det finns ett hopp in i eller ut ur en instruktion är den instruktionen ett strukturerat block. (Den här regeln innehåller ett anrop till longjmp(3C) eller användning av throw, även om en uppmaning till exit är tillåten.) Om dess körning alltid börjar vid öppningen { och alltid slutar vid stängningen }, är ett sammansatt uttryck ett strukturerat block. Ett uttryck, urvalsinstruktion, iterationsinstruktion eller try-block är ett strukturerat block om motsvarande sammansatta uttryck som erhålls genom att omsluta det med { och } skulle vara ett strukturerat block. En jump-instruktion, en etikettsats eller en deklarationssats är inte ett strukturerat block.

  • arbetslag

    En eller flera trådar som samarbetar vid utförandet av en konstruktion.

  • tråd

    En körningsentitet med ett seriellt kontrollflöde, en uppsättning privata variabler och åtkomst till delade variabler.

  • variabel

    En identifierare, valfritt kvalificerad efter namnområdesnamn, som namnger ett objekt.

1.3 Körningsmodell

OpenMP använder fork-join-modellen för parallell körning. Även om den här förgreningsmodellen kan vara användbar för att lösa olika problem är den skräddarsydd för stora matrisbaserade program. OpenMP är avsett att stödja program som körs korrekt både som parallella program (många körningstrådar och ett fullständigt OpenMP-supportbibliotek). Det är också för program som körs korrekt som sekventiella program (direktiv ignoreras och ett enkelt OpenMP stubs-bibliotek). Det är dock möjligt och tillåtet att utveckla ett program som inte fungerar korrekt när det körs sekventiellt. Dessutom kan olika parallellitetsgrader resultera i olika numeriska resultat på grund av ändringar i associationen för numeriska åtgärder. En seriell addition-reduktion kan till exempel ha ett annat mönster för adderingsassociationer än en parallell reduktion. Dessa olika associationer kan ändra resultatet av flyttalstillägg.

Ett program som skrivits med OpenMP C/C++-API:et börjar köras som en enda körningstråd som kallas huvudtråden. Mastertråden körs i en seriell region tills den första parallella konstruktionen påträffas. I OpenMP C/C++-API:et parallel utgör direktivet en parallell konstruktion. När en parallell konstruktion påträffas skapar huvudtråden ett team med trådar och mastern blir huvudhanterare för teamet. Varje tråd i teamet kör satserna i den dynamiska omfattningen av en parallell region, förutom konstruktionerna för delning av uppgifter. Alla trådar i teamet måste stöta på arbetsdelningskonstruktioner i samma ordning, och en eller flera av trådarna kör instruktionerna i det associerade strukturerade blocket. Den barriär som är underförstådd i slutet av en arbetsdelningskonstruktion utan en nowait-klausul utförs av alla trådar i teamet.

Om en tråd ändrar ett delat objekt påverkar den inte bara sin egen körningsmiljö, utan även de andra trådarna i programmet. Ändringen är garanterad att vara klar, ur en annan tråds synvinkel, vid nästa sekvenspunkt (enligt definitionen i basspråket) endast om objektet deklareras vara flyktigt. Annars är ändringen garanterad att vara klar efter den första ändringstråden. De andra trådarna ser sedan (eller samtidigt) ett flush direktiv som anger objektet (antingen implicit eller explicit). När de flush direktiv som underförstås av andra OpenMP-direktiv inte garanterar rätt ordning på biverkningar, är det programmerarens ansvar att tillhandahålla ytterligare, explicita flush direktiv.

När den parallella konstruktionen har slutförts synkroniseras trådarna i teamet vid en implicit barriär, och endast huvudtråden fortsätter att köras. Valfritt antal parallella konstruktioner kan anges i ett enda program. Därför kan ett program forka och sammanfogas många gånger under körningen.

Med OpenMP C/C++-API:et kan programmerare använda direktiv i funktioner som anropas inifrån parallella konstruktioner. Direktiv som inte förekommer i den lexikala omfattningen av en parallell konstruktion men som kan ligga i den dynamiska omfattningen kallas överblivna direktiv. Med överblivna direktiv kan programmerare köra större delar av sitt program parallellt, med endast minimala ändringar i sekventiellt program. Med den här funktionen kan du koda parallella konstruktioner på de översta nivåerna i programanropsträdet och använda direktiv för att styra körningen i någon av de anropade funktionerna.

Osynkroniserade anrop till C- och C++-utdatafunktioner som skriver till samma fil kan resultera i utdata där data som skrivs av olika trådar visas i nondeterministisk ordning. På samma sätt kan osynkroniserade anrop till indatafunktioner som läser från samma fil läsa data i icke-terministisk ordning. Osynkroniserad användning av I/O, så att varje tråd kommer åt en annan fil, ger samma resultat som seriell körning av I/O-funktionerna.

1.4 Efterlevnad

En implementering av OpenMP C/C++-API:et är OpenMP-kompatibel om den identifierar och bevarar semantiken för alla element i denna specifikation, enligt kapitlen 1, 2, 3, 4 och bilaga C. Tillägg A, B, D, E och F är endast i informationssyfte och ingår inte i specifikationen. Implementeringar som endast innehåller en delmängd av API:et är inte OpenMP-kompatibla.

OpenMP C- och C++-API:et är ett tillägg till det basspråk som stöds av en implementering. Om basspråket inte stöder en språkkonstruktion eller ett tillägg som visas i det här dokumentet krävs inte OpenMP-implementeringen för att stödja den.

Alla C- och C++-standardbiblioteksfunktioner och inbyggda funktioner (dvs. funktioner som kompilatorn har specifika kunskaper om) måste vara trådsäkra. Osynkroniserad användning av trådsäkra funktioner av olika trådar i en parallell region ger inte odefinierat beteende. Beteendet kanske inte är detsamma som i ett sekventiellt område. (En slumptalsgenereringsfunktion är ett exempel.)

OpenMP C/C++ API anger att vissa beteenden är implementeringsdefinierade. En överensstämmande OpenMP-implementering krävs för att definiera och dokumentera dess beteende i dessa fall. En lista över implementeringsdefinierade beteenden finns i bilaga E.

1.5 Normativa referenser

  • ISO/IEC 9899:1999, Information Technology – Programmeringsspråk – C. Den här OpenMP API-specifikationen refererar till ISO/IEC 9899:1999 som C99.

  • ISO/IEC 9899:1990, Information Technology – Programmeringsspråk – C. Den här OpenMP API-specifikationen refererar till ISO/IEC 9899:1990 som C90.

  • ISO/IEC 14882:1998, Information Technology – Programmeringsspråk – C++. Den här OpenMP API-specifikationen refererar till ISO/IEC 14882:1998 som C++.

Om denna OpenMP API-specifikation refererar till C, hänvisas till det basspråk som stöds av implementeringen.

1.6 Organisation