MP öffnen
OpenMP ist eine Anwendungsprogrammierschnittstelle (API) für die Multithread -Programmierung mit gemeinsamem Speicher auf mehreren Plattformen. Es ermöglicht das Hinzufügen von Parallelität zu Programmen, die in C, C++ und Fortran geschrieben wurden, basierend auf dem Fork-Join- Ausführungsmodell . Es ist auf vielen Architekturen verfügbar , einschließlich der Unix- und Microsoft Windows-Plattformen. Es besteht aus einer Reihe von Compiler-Direktiven , Bibliotheksroutinen und Umgebungsvariablen , die das Laufzeitverhalten beeinflussen.
OpenMP wurde gemeinsam von Hardware- und Softwareanbietern definiert und ist ein portables und skalierbares Programmiermodell , das Programmierern eine einfache und flexible Schnittstelle für die parallele Anwendungsentwicklung für Plattformen von Desktops bis hin zu Supercomputern bietet . Eine mit einem hybriden parallelen Programmiermodell erstellte Anwendung kann auf einem Cluster von Computern mit OpenMP und MPI oder über OpenMP-Erweiterungen für verteilte Speichersysteme ausgeführt werden .
Ausführungsmodell
OpenMP basiert auf dem Fork-Join- Modell, einem von Unix -Systemen stammenden Paradigma , bei dem eine sehr schwere Aufgabe in K Threads (Fork) mit geringerem Gewicht aufgeteilt wird, um dann deren Ergebnisse am Ende „einzusammeln“ und zu einem zusammenzufügen Einzelergebnis (Join).
Wenn eine OpenMP - Compiler-Direktive enthalten ist , impliziert dies, dass eine obligatorische Synchronisation im gesamten Block enthalten ist. Das heißt, der Codeblock wird als parallel markiert und Threads werden gemäß den Eigenschaften gestartet, die uns die Direktive gibt, und am Ende wird es eine Barriere für die Synchronisierung der verschiedenen Threads geben (sofern nicht das Gegenteil der Fall ist implizit mit der Direktive nowait angegeben ). Diese Art der Ausführung wird Fork-Join genannt .
OpenMP unterstützt auch das Aufgabenparallelitätsmodell . Das Thread-Team des parallelen Codeblocks führt die in diesem Block angegebenen Aufgaben aus. Tasks ermöglichen asynchrone Parallelität. Seit der 2013 veröffentlichten Version 4.0 unterstützt es die Angabe von Abhängigkeiten zwischen Aufgaben, die Verlagerung der Aufgabenplanung und deren Ausführung in die OpenMP-Laufzeitbibliothek. Die Ausführungs-Threads führen die Aufgaben aus, sobald sie verfügbar sind (ihre Abhängigkeiten sind bereits erfüllt). Die Verwendung von Aufgaben führt zu einer Synchronisierung mit einer feineren Granularität. Die Verwendung von Barrieren ist nicht unbedingt erforderlich, sodass Threads weiterhin verfügbare Aufgaben ausführen können, ohne warten zu müssen, bis das gesamte Team von Threads einen parallelen Block beendet. Durch die Verwendung von Aufgaben mit Abhängigkeiten wird ein Diagramm erstellt, sodass bei der Auswahl von Aufgaben zur Ausführung Diagrammeigenschaften angewendet werden können.
Abgesehen von der Verwendung von Hardware-Implementierungen der OpenMP-Laufzeitbibliothek (z. B. in FPGAs ) sind die Kostenüberschreitungen der Aufgaben höher. Diese zusätzlichen Kosten müssen durch die potenzielle zusätzliche Parallelität amortisiert werden, die die Aufgaben offenlegen.
Grundlegende Syntax
Die grundlegende Syntax, die wir in einer OpenMP- Direktive finden, ist für C / C++ :
# Pragma omp <Direktive> [Klausel [ , ...] ...]
für Fortran :
!$OMP PARALLEL <Direktive> [Klauseln]
[ Codeblock ] ! $ OMP END <Direktive>
Nachfolgend sind einige der verfügbaren Anweisungen und Klauseln aufgeführt, die für die von OpenMP angebotenen Anweisungen gelten.
Direktiven
Konstruktoren werden auch oft genannt :
parallel: Diese Direktive sagt uns, dass der Teil des Codes , der sie enthält, von mehreren Threads ausgeführt werden kann. Eine implizite Aufgabe wird für jeden Thread erstellt, der zu dem von der erstellten Thread-Team gehörtparallel.
Dieses Code-Snippet versucht, das Potenzial der Parallelität in einer Aufgabe einer geometrischen Reihe zu nutzen, die für die Gleichung gegen Unendlich strebt:
/* Juan Carlos Lanuza Lazo
MGA-NI 27 / Apr / 2017
Beispiel für parallele Summierung einer harmonischen Reihe */
#include <omp.h>
#include <stdio.h>
#define GRENZE 1000000000000
int main ( void )
{
doppelter String = 0 ;
lang lang ich ;
#pragma omp parallel
{
#pragma omp for reduction(+:string)
for ( i = 1 ; i <= LIMIT ; i ++ )
Reihe += 1.0 / i ;
}
printf ( "Wert von String: %.5f \n " , string );
0 zurückgeben ;
}
for: Das Team von Threads, das auf das trifft,forführt einen oder mehrere Bruchteile von Iterationen aus, indem es die durch die Direktive begrenzte Schleife unter den Threads des Teams aufteilt (die Größe jeder Partition hängt von den optionalen Klauseln ab, die dem hinzugefügt werdenfor). Sein Format ist:#pragma omp parallel for [Klausel, ... , Klausel]
. Jeder Bruchteil von Iterationen ist eine implizite Aufgabe (der Programmierer hat die Schleife nicht manuell partitioniert und eine Aufgabe für jeden Block notiert).sectiony Abschnitte : Gibt Abschnitte an, die parallel, aber von einem einzigen Thread ausgeführt werden können .single: Der Teil des Codes, der diese Direktive definiert, nur ein Thread aller gestarteten kann ausgeführt werden, und es muss nicht der übergeordnete Thread sein.master: Der definierte Teil des Codes kann nur vom übergeordneten Thread ausgeführt werden .critical: In diesem Abschnitt kann sich nur ein Thread befinden. Sie definieren kritische Abschnitte oder Rennbedingungen .atomic: Wird verwendet, wenn die Operation nur einen Speicherort betrifft und jeweils nur von einem Thread aktualisiert werden muss. Operationen wie x++ oder --x sind diejenigen, die diese Klausel verwenden.flushHinweis: Diese Direktive löst die Konsistenz auf, indem sie einen geänderten Wert einer Variablen, der von einem anderen Thread in paralleler Verarbeitung ausgeführt wurde, an alle Threads exportiert.barrier: Erstellt eine explizite Barriere, bei der Threads warten, bis das gesamte Team sie erreicht hat.task: Ermöglicht die asynchrone Ausführung mit expliziten Aufgaben. Der Codeblock innerhalb der Direktivetaskwird von einem einzelnen Thread ausgeführt, und die Aufgabe wird von dem Thread instanziiert, der auf die Direktive trifft. Aus diesem Grund ist es ratsam, diese Direktive innerhalb einer Direktive zu verwendensingle, um zu vermeiden, dass dieselbe Aufgabe so oft erstellt (und ausgeführt) wird, wie es Threads gibt. Sein Format ist:#pragma omp task [cláusulas]. Wenn die Aufgabe instanziiert wird, wird sie in eine anstehende Warteschlange eingefügt. Aufgaben im Backlog werden von der OpenMP-Implementierung basierend auf ihren erfüllten Abhängigkeiten und ihrer Priorität ausgewählt. Die ausgewählten Aufgaben werden zur Ausführung in die Warteschlange gestellt. Threads aus dem aktiven Team greifen Aufgaben aus dieser Warteschlange auf und führen sie aus. Verwendung vontaskmitsingle:
#define NUM_ITERS 1000000
#pragma omp parallel
{
int32_t BS = NUM_ITERS / omp_get_num_threads ();
#pragma omp single
{
for ( int i = 0 ; i < NUM_ITERS ; i += BS ) {
int32_t obere = i + (( NUM_ITERS - BS >= 0 ) ? BS : NUM_ITERS - BS );
#pragma omp task firstprivate(i,upper)
{
für ( int ii = i ; ii < obere ; ii ++ )
a [ ii ] += b [ ii ] * c [ ii ];
}
}
#pragma omp taskwait
}
}
taskyield: Ermöglicht einer Aufgabe, die Kontrolle über den Prozessorkern an eine andere Aufgabe abzugeben.taskwait: Ähnlich wiebarrier. Der Task-Instanziator-Thread bleibt darin wartentaskwait, bis alle Tasks vor ihmtaskwaitihre Ausführung beendet haben. Es ist sinnlos, auf verschachtelte Tasks zu warten, die einetaskwaitVerschachtelung erfordern. Alle Threads, was auch immer sie sein mögen, überprüfen die Warteschlange auf Aufgaben, die zur Ausführung bereit sind, während sie in einer Barriere bleiben, sei es implizit oder explizit. Wenn es anstehende Aufgaben gibt, werden sie diese ausführen.
Datensichtbarkeitsklauseln
shared(valor-i_1, ..., valor-i_N): Die Daten in der parallelen Region werden gemeinsam genutzt, was bedeutet, dass sie für alle Threads sichtbar und zugänglich sind. Per Definition werden alle im parallelen Bereich arbeitenden Variablen mit Ausnahme des Iterationszählers gemeinsam genutzt.private(valor-i_1, ..., valor-i_N): Die Daten in der parallelen Region mit dem Namen byprivatewerden in den lokalen Speicherbereich des Threads (hauptsächlich seinen Stack) kopiert, was bedeutet, dass jeder Thread sie als temporäre Variable verwendet. Eine private Variable wird nicht initialisiert und auch nicht außerhalb des Parallelbereichs gehalten. Per Definition ist der Iterationszähler in OpenMP privat.firstprivate(valor-i_1, ..., valor-i_N): Jeder Thread hat eine lokale Kopie der Daten. Die lokale Kopie wird mit dem Wert der globalen Kopie zu dem Zeitpunkt initialisiert, zu dem die Direktive angetroffen wird, auf die sich die Klausel bezieht.lastprivate(valor-i_1, ..., valor-i_N): Jeder Thread hat eine lokale Kopie der Daten. Die globale Kopie wird von dem Thread aktualisiert, der die letzte Iteration gemäß der sequentiellen Reihenfolge des Programms ausführt.default: Ermöglicht dem Programmierer, alle Variablen in der parallelen Region für C/C++ gemeinsam genutzt oder nicht oder für Fortran gemeinsam genutzt, zuerst privat, privat oder keine zu machen. Die Option none zwingt den Programmierer zu deklarieren, welchen Typ jede Variable in der parallelen Region haben wird.
Die folgenden Klauseln definieren Sammeloperationen:
reduction(tipo:valor-i_1, ..., valor-i_N): Jeder Thread privatisiert die aufgelisteten Variablen und am Ende des Abschnitts der Direktive, in dem die Klausel erscheint, aktualisieren die verschiedenen Threads die globale Variable, von der die private Kopie abgeleitet wird, indem sie die durch die Klausel angegebene Operation ausführenreduction. Dies vermeidet Race-Conditions . DietipoWerte können sein: +, -, *, /, min, max oder benutzerdefiniert.
Planungsklauseln
schedule(omp_sched_t tipo, int chunk_size): Dies ist nützlich, wenn die Nutzlast eine do-Schleife oder eine for-Schleife ist. Iterationen werden Threads basierend auf der in der Klausel definierten Methode zugewiesen. Die drei Arten der Planung sind:
static: Hier werden alle Iterationen auf die Threads verteilt, bevor sie die Schleife ausführen. Aneinandergrenzende Iterationen werden gleichmäßig auf alle Threads verteilt. Wenn Sie eine Ganzzahl als Chunk -Parameter angeben, werden so viele zusammenhängende Iterationen an denselben Thread verteilt, wie der Chunk angibt.dynamic: Hier werden wie bei static alle Iterationen auf die Threads verteilt. Wenn ein bestimmter Thread seine zugewiesenen Iterationen beendet, führt er dann eine der Iterationen aus, die ausgeführt werden sollten. Der Chunk- Parameter definiert die Anzahl zusammenhängender Iterationen, die jeder Thread gleichzeitig ausführen wird.guided: Einem Thread wird eine große Anzahl zusammenhängender Iterationen zugewiesen. Diese Anzahl von Iterationen verringert sich exponentiell mit jeder neuen Zuweisung bis zu einem Minimum, das durch den Chunk- Parameter angegeben wird .
Wenn keine Klausel eingefügt wird, scheduleist der Standardzeitplan schedule(static,1). Das heißt, die Iterationen der Schleife werden in einer Round-Robin- Weise verteilt , eine nach der anderen.
Abhängigkeitsklauseln
depends(tipo:valor-i_1,valor-i_2...): Je nach Art der Abhängigkeit (Eingabe, Ausgabe oder beides) werden Aufgaben vor oder nach anderen Aufgaben in die verfügbare Warteschlange gestellt, eine Entscheidung, die von der Laufzeitbibliothek getroffen wird. Es gibt drei Arten von Abhängigkeiten:
in: Abhängigkeit wird gelesen. Die Aufgabe (Task) liest den in der Speicheradresse gespeicherten Wert des i-Wertes.out: Abhängigkeit ist beschreibbar. Die Aufgabe (Task) schreibt an die Speicheradresse des i-Wertes.inout: Die Abhängigkeit wird gelesen und geschrieben. Die Aufgabe (Task) liest und schreibt an der Speicheradresse des i-Werts.
Wenn eine Aufgabe eine Abhängigkeit inhat und eine andere zuvor instanziierte Aufgabe eine Abhängigkeit outvom gleichen i-Wert hat, dann inwird die Aufgabe mit der nach der ausgeführt out. Da Lesevorgänge den Speicher nicht verändern, können zwei Tasks mit einem inEnvelope desselben i-Werts in beliebiger Reihenfolge und von jedem verfügbaren Thread ausgeführt werden. Stattdessen werden zwei Schreibabhängigkeiten auf demselben i-Wert immer serialisiert, da sie den Speicher modifizieren. Diese Konzepte ähneln den bestehenden Abhängigkeiten zwischen Befehlen in einem Mikroprozessor mit Out-of-Order-Ausführung , bei dem drei Arten von Abhängigkeiten auftreten können:
- RAW: (Lesen nach Schreiben). Lesen nach dem Schreiben.
- WAR: (Nach dem Lesen schreiben). Schreiben nach dem Lesen.
- WAW: (Schreiben nach Schreiben). Schreiben Sie nach dem Schreiben.
RAW ist die einzig wahre und unüberwindbare Abhängigkeit. WAR und WAW werden als falsche Abhängigkeiten angesehen, da die Abhängigkeit besteht, weil sie denselben Namen haben (Speicheradresse des i-Werts). Durch Umbenennen der Adresse des i-Werts (Kopieren an eine andere Speicheradresse) können falsche Abhängigkeiten entfernt werden. Wenn die Aufgabe diese Speicheradresse nicht liest, schreibt sie sie nur, für praktische Zwecke spielt es keine Rolle, ob eine andere vorherige Anweisung sie liest. Es ist auch egal, ob ein anderer vorheriger Befehl an dieselbe Adresse schreibt, da er den aktualisierten Wert nicht benötigt. Wenn jedoch immer dieselbe Speicheradresse verwendet wird, muss die Programmreihenfolge beibehalten werden, sodass der letzte Wert derjenige ist, der die Reihenfolge der Instantiierung der Tasks angibt. Dies verhindert bei einer Ausführung außerhalb der Reihenfolge, dass ein vorheriger Lesevorgang Daten liest, die aus der Sicht des Lesevorgangs später erscheinen müssten. Es vermeidet auch den Fall, wo der letzte Schreibvorgang dem ältesten Schreibvorgang vorausgeht, so dass der alte Wert der letzte widerzuspiegelnde Wert sein wird, wenn der verbleibende Wert der neueste Schreibvorgang sein sollte. Wenn die Speicheradresse umbenannt wird, spielt die Reihenfolge der Anweisungen keine Rolle, da die abhängigen Tasks die Ausführungsreihenfolge in Bezug auf die neue Speicheradresse beibehalten, wodurch die WAR- und WAW-Abhängigkeiten beseitigt werden.
Funktionen
Die OpenMP- API verfügt über eine Reihe von Funktionen zum Abrufen von Informationen und zum Konfigurieren der parallelen Umgebung. Es ermöglicht auch die Verwaltung von Vorhängeschlössern (Schlössern) und die Durchführung von Zeitmessungen. Zusätzlich zu den hier gezeigten Funktionen hat jede OpenMP-Implementierung ihre eigenen Funktionen und Umgebungsvariablen. Beispielsweise hat GNU OpenMP (GOMP, GNU OpenMP) seine eigenen Umgebungsvariablen. [ 1 ] Es gibt Teile der Spezifikation, die implementierungsabhängig sind, sodass sich das Programm nicht gleich verhalten muss, wenn die Binärdatei zuerst mit einer Implementierung und dann mit einer anderen erstellt wird. Beispielsweise gibt das Erstellen verschachtelter paralleler Regionen nicht an, wie die Threads für die verschachtelten Regionen bereitgestellt werden sollen. Im Fall von GNU OpenMP verwaltet es ein einzelnes Team von Threads und lässt es wachsen oder schrumpfen, je nachdem, wie viele Threads von der aktiven parallelen Region angefordert werden. Dies ist eine Optimierung, die dabei hilft, die Datenlokalität beizubehalten und den Aufwand für das Erstellen und Zerstören von Threads zu verringern. Eine Bereitstellung verwaltet jedoch möglicherweise kein einzelnes Team und erstellt nicht ganze neue Teams. Dies bewirkt das Auswerfen von Threads aus parallelen Vorgängerregionen. Die Zuordnung von Kennungen zu Prozessoren folgt nicht immer der gleichen Reihenfolge, sofern nicht anders angegeben. Wenn der Programmcode für die Zuweisung von zu verarbeitenden Daten von der Thread-Kennung abhängt, kann die räumliche Lokalität des Programms verloren gehen. Das Erstellen und Zerstören mehrerer Thread-Teams ist auch zeitaufwändiger als das Wiederverwenden vorhandener Thread-Teams.
Die hier aufgeführten Funktionen entsprechen der Version 4.5 des OpenMP-Standards.
Funktionen zur Steuerung von Threads, Prozessoren und der parallelen Umgebung
Diese Funktionen sind gemäß den C-Sprachregeln gebunden und lösen keine Ausnahmen aus.
omp_get_active_level(): Parallele Regionen, die zum Zeitpunkt des Aufrufs der Funktion aktiv sind.omp_get_ancestor_thread_num(int level): Gibt die TID (Thread-ID) auf der betreffenden Parallelitätsverschachtelungsebene zurück, die dem Thread entspricht, der die Funktion aufruft.omp_get_cancellation(): Unterstützt die verwendete OpenMP-Implementierung die Stornierung? Gesteuert durch die UmgebungsvariableOMP_CANCELLATION.omp_get_default_device(): Holen Sie sich das Standardgerät in Regionentarget, die keine Klausel habendevice.omp_get_dynamic(): Ist die Funktion zur Teamerstellung mit dynamischer Größe aktiv? Wert gesteuert durch UmgebungsvariableOMP_DYNAMICoderomp_set_dynamic().omp_get_level(): Abrufen der Verschachtelungsebene zum Zeitpunkt des Aufrufs der Funktion.omp_get_max_active_levels(): Wie viele aktive parallele Regionen sind maximal zulässig?omp_get_max_task_priority(): Was ist die höchste zulässige Priorität für eine explizite Aufgabe?omp_get_max_threads(): Was ist die maximale Anzahl von Threads in der aktuellen parallelen Region, die nicht von verwendet wirdnum_threads?omp_get_nested(): Sind verschachtelte parallele Regionen erlaubt? Wert gesteuert durch UmgebungsvariableOMP_NESTEDoder Funktionomp_set_nested().omp_get_num_devices(): Wie viele Beschleunigergeräte gibt es?omp_get_num_procs(): Wie viele Prozessoren (Kerne) sind im aktuellen Gerät verfügbar?omp_get_num_teams(): Wie viele Thread-Teams gibt es in der aktuellen Parallelregion?omp_get_num_threads(): Aus wie vielen Threads besteht das aktuell aktive Thread-Team? In einem sequentiellen Abschnitt wird 1 zurückgegeben. Die Standardgröße kann mit der Variablen initialisiert werdenOMP_NUM_THREADS. Während der Ausführung können Sie entweder die Klauselnum_threadsoder die Funktion verwendenomp_set_num_threads(int num_threads). Wenn keines der oben genannten Elemente verwendet wird und der Wert vonOMP_DYNAMICdeaktiviert ist, wird eine Gesamtzahl von Threads konfiguriert, die der Gesamtzahl verfügbarer Prozessoren entspricht.omp_get_proc_bind(): Sind Threads mit bestimmten Prozessoren verankert? Die Funktion gibt den Bindungstyp zurück, der einer der folgenden sein kann:omp_proc_bind_false,omp_proc_bind_true,omp_proc_bind_master,omp_proc_bind_closeoderomp_proc_bind_spread. Der Ankertyp wird beim Programmstart mit der Umgebungsvariable gesetztOMP_PROC_BIND.omp_get_schedule(): Was ist die Standardplanungsmethode?omp_get_team_num(): Wie lautet die aktuelle Thread-Teamkennung?omp_get_team_size(): Wie groß ist das aktive Streicherteam?omp_get_thread_limit(): Wie viele Threads werden maximal unterstützt?omp_get_thread_num(): Wie lautet die Kennung innerhalb des aktiven Teams des Threads, der die Funktion aufruft?omp_in_parallel(): Liegt der Faden in einem Parallelbereich?omp_in_final(): Befinden wir uns in einer expliziten Aufgabe (task) oder wird der Bereich der expliziten Aufgabe als ausgeführtfinal?omp_is_initial_device(): Befinden wir uns zum Zeitpunkt des Aufrufs der Funktion im Host oder in einem Beschleuniger?omp_set_default_device(int device_num): Legen Sie das Standardgerät für Regionentargetfest , die keine Klausel habendevice.omp_set_dynamic(int dynamic_threads): Aktivieren/deaktivieren Sie die dynamische Regulierung der Größe der Fadenausrüstung.omp_set_max_active_levels(int max_levels): Begrenzt die Anzahl aktiver paralleler Regionen.omp_set_nested(int nested): Verschachtelte parallele Regionen zulassen oder nicht zulassen.omp_set_num_threads(int num_threads): Legen Sie die maximale Anzahl von Threads in einem Thread-Team fest.omp_set_schedule(omp_sched_t kind, int chunk_size)schedule: Legen Sie die Standardplanungsmethode fest ( ). Der Wert vonkindkannomp_sched_static,omp_sched_dynamic,omp_sched_guidedoder seinomp_sched_auto.
Sperren
omp_init_lock(omp_lock_t *lock): Eine Sperre initialisieren.omp_set_lock(omp_lock_t *lock): Warten Sie, bis die Sperre inaktiv ist, und aktivieren Sie sie für den aufrufenden Thread.omp_test_lock(omp_lock_t *lock): Prüfen Sie, ob die Sperre inaktiv ist, und aktivieren Sie sie für den aufrufenden Thread, wenn die Prüfung positiv ist.omp_unset_lock(omp_lock_t *lock): Einfaches Vorhängeschloss deaktivieren.omp_destroy_lock(omp_lock_t *lock): Zerstöre ein einfaches Vorhängeschloss.omp_init_nest_lock(omp_lock_t *lock): Initialisiert eine verschachtelte Sperre.omp_set_nest_lock(omp_lock_t *lock): Warten Sie, bis die verschachtelte Sperre inaktiv ist, und aktivieren Sie sie für den aufrufenden Thread.omp_test_nest_lock(omp_lock_t *lock): Prüfen Sie, ob die Sperre inaktiv ist, und aktivieren Sie sie für den aufrufenden Thread, wenn die Prüfung positiv ist.omp_unset_nest_lock(omp_lock_t *lock): Verschachtelte Sperre deaktivieren.omp_destroy_nest_lock(omp_lock_t *lock): Zerstöre eine verschachtelte Sperre.
Funktionen zur Zeitmessung
omp_get_wtick: Erhalten Sie die Genauigkeit der Stoppuhr: Wie viele Sekunden vergehen zwischen zwei Uhr-Ticks.omp_get_wtime: Abrufen der Stoppuhrzeit. Die Zeit entspricht der Echtzeit, also der Programmausführungszeit, nicht der Prozesszeit. Die Verarbeitungszeit wäre die Summe der Aktivitätszeiten aller Threads. Die Maßeinheit ist Sekunden. Es gibt keine Garantie, dass zwei verschiedene Threads die gleiche Zeit liefern.
Umgebungsvariablen
OMP_CANCELLATION: Konfiguriert die Möglichkeit der Verwendung der Direktive#pragma omp cancelOMP_DISPLAY_ENV: Zeigt die OpenMP-Version und Umgebungsvariablen an.OMP_DEFAULT_DEVICE: Legen Sie das in den Regionen verwendete Gerät festtargetOMP_DYNAMIC: Aktiviert die dynamische Fadenanpassung.OMP_MAX_ACTIVE_LEVELS: Legen Sie die maximale Anzahl verschachtelter paralleler Regionen fest.OMP_MAX_TASK_PRIORITY: Legen Sie die höchste Priorität einertask.OMP_NESTED: Aktiviert die Verwendung von verschachtelten parallelen Regionen. WennTRUEdann Mitglieder eines Thread-Teams neue Thread-Teams erstellen können.OMP_NUM_THREADS: Legen Sie die Anzahl gleichzeitiger Threads fest.OMP_PROC_BIND: Legt fest, ob Threads zwischen Prozessoren verschoben werden können.OMP_PLACES: Konfiguriert die CPUs, auf denen die Threads fixiert werden sollen.OMP_STACKSIZE: Legt die Stapelgröße jedes Threads fest.OMP_SCHEDULE: Legen Sie denscheduleStandardtyp fest.OMP_THREAD_LIMIT: Legen Sie die maximale Anzahl von Threads fest.OMP_WAIT_POLICY: Konfiguriert den Wartealgorithmus an den Schranken (barrier). Es kann aktives oder passives Warten sein.
Versionen
Die neueste Version von OpenMP ist 4.5. In mehr als 20 Jahren wurden folgende Versionen veröffentlicht: [ 2 ]
- OpenMP 1.0: Veröffentlicht im Oktober 1997, nur Fortran. Parallele Regionen, Schleifen
for, Barrieren und andere grundlegende Thread-Synchronisationsmechanismen. - OpenMP 1.1: Veröffentlicht im November 1999, eine interpretative Errata.
- OpenMP 2.0: Veröffentlicht im November 2000 (Fortran) und März 2002 (C/C++).
num_threadsZusätze wie die , und -Klauselncopyprivateoder die gettimeomp_get_wtimeundomp_get_wtick. C99-Vektoren variabler Länge sind erlaubt, und Klauseln, die auf Datentypen wiefirstprivate,lastprivateund , wirken, können mit ihnen verwendet werdenprivate. - OpenMP 2.5: Veröffentlicht im Mai 2005. Vereint C, C++ und Fortran. Führt interne Kontrollvariablen (ICVs) ein. Neudefinition der Terminologie, Präzisierung der Erläuterungen zu den Weisungen und Korrektur von Errata.
- OpenMP 3.0: Veröffentlicht im Mai 2008. Fügt explizite Aufgaben hinzu (
task). Direktive hinzugefügttaskwait. Planung hinzugefügtauto. UmgebungsvariableOMP_STACKSIZEund hinzugefügtOMP_WAIT_POLICY. Zusätzliche Funktionen, Änderungen in der Definition einiger Konzepte. - OpenMP 3.1: Veröffentlicht im Juli 2011. Hinzufügung von Klauseln
final,mergeableundtaskyieldfür explizite Aufgaben. Richtlinieatomicum die Klauselnread,write,captureund erweitertupdate.minReduktions- und Additionsoperatorenmaxin C und C++.OMP_PROC_BINDhinzugefügt. - OpenMP 4.0: Veröffentlicht im Juli 2013. Fügt eine Abhängigkeitsspezifikation (
depends) in expliziten Aufgaben sowie die Möglichkeit hinzu, Coderegionen anzugeben, die auf Beschleunigergeräten ausgeführt werden sollen ( Geräteabladung ). Klauselproc_bindzusammen mit UmgebungsvariableOMP_PLACESund Funktion hinzugefügtomp_get_proc_bind. Direktiven zur Unterstützung von SIMD- Parallelität und -Beschleunigern hinzugefügt. UmgebungsvariableOMP_DEFAULT_DEVICE. Richtlinietaskgroup. Richtliniedeclare reduction. Direktivencancelundcancellation pointzusammen mit der Funktionomp_get_cancellationund der VariablenOMP_CANCELLATION. UmgebungsvariableOMP_DISPLAY_ENV. Die Beispiele (Anhang A) befinden sich jetzt in einem separaten Dokument. - OpenMP 4.5: Veröffentlicht im November 2015. Fügt Unterstützung für einige Funktionen von Fortran 2003 hinzu. Parameter zur Schleifendirektivenklausel
orderedzusammen mit neuen Klauseln zur Direktive hinzugefügtordered, um das Verschachteln von Schleifen mit Abhängigkeiten zwischen Iterationen zu ermöglichen. Aus demselben Grund werden der Klausel der Typsourceund die Abhängigkeiten hinzugefügt . Die Klausel wird hinzugefügt , um der Laufzeitbibliothek Hinweise zur Priorität der Tasks zu geben. Folglich wurden die Funktion und die Umgebungsvariable hinzugefügt . Die Klausel wird der Direktive hinzugefügt, und die Klausel wird der Direktive hinzugefügt, um eine Interaktion mit dem nativen Code einer Beschleunigervorrichtung zu ermöglichen. Es gibt weitere Klauseln in Bezug auf Beschleunigergeräte, um SIMD zuzulassen, unstrukturierte Daten (nicht aufeinanderfolgend im Speicher) in Beschleunigern abzubilden, explizite Speicherverwaltungsfunktionen in Beschleunigern (Speicher reservieren, Speicher freigeben, Daten übertragen und Speicher zuweisen). Abgesehen von diesen Ergänzungen für Beschleuniger werden andere bereits bestehende Richtlinien und Klauseln verbessert.sinkdependpriorityomp_get_max_task_priorityOMP_MAX_TASK_PRIORITYuse_device_ptrtarget datais_device_ptrtarget
Compiler und Programmierumgebungen, die OpenMP unterstützen
- GNU GCC bis OpenMP 4.5. Es unterstützt derzeit teilweise die Versionen 5.0 und 5.1 von OpenMP.
- XL C/C++/Fortran von IBM , bis OpenMP 3.1 und teilweise OpenMP 4.5 (beschleunigt mit NVIDIA GPUs).
- Intel C/C++/Fortran, bis OpenMP 4.5. Unterstützt teilweise die OpenMP-Versionen 5.0 und 5.1
- Oracle C/C++/Fortran – Oracle Developer Studio 12.6-Compiler bis OpenMP 4.0.
- PGI C/C++/Fortran, bis OpenMP 3.1.
- Absoft Pro Fortran Fortran, bis OpenMP 3.1.
- Lahey/Fujitsu Fortran 95 C/C++/Fortran, bis OpenMP 3.1.
- PathScale C/C++/Fortran, bis OpenMP 2.5, teilweise OpenMP 3.x und OpenMP 4.0.
- Cray C/C++/Fortran, bis OpenMP 4.0 und teilweise OpenMP 4.5.
- NAG nagfor, bis OpenMP 3.1.
- OpenHU Research Compiler C/C++/Fortran, bis OpenMP 2.5, teilweise OpenMP 3.0.
- LLVM -Clang, bis OpenMP 4.0 und teilweise OpenMP 4.5 (Accelerator-Unterstützung fehlt).
- LLNL Rose Research Compiler C/C++/Fortran, bis zu OpenMP 3.0 und einige OpenMP 4.0-Beschleunigerfunktionen.
- Appentra Solutions Parallelware Compiler Parallware Suite C/C++, bis OpenMP 4.0.
- Texas Instruments C, bis zu OpenMP 3.0 mit OpenMP 4.0-Beschleunigerdirektiven.
- Mercurium C/C++/Fortran vom Barcelona Supercomputing Center , OpenMP 3.1 und OpenMP 4.0, beide teilweise.
- ARM C/C++/Fortran, teilweise bis OpenMP 3.1 und OpenMP 4.0/4.5 (Beschleunigerfunktionen fehlen). Nur für Linux unterstützt bis zu OpenMP 3.5.
- NVIDIA HPC (und PGI ) Compiler C/C++/Fortran, der teilweise bis Version 5.1 unterstützt und die Verwendung von GPUs erlaubt.
- OpenUH Research Compiler C/C++/Fortran: unterstützt die Versionen 2.5 und 3.0 auf 32-Bit- oder 64-Bit-Linux.
- Siemens Sourcery CodeBench Lite – C/C++/Fortran, unterstützt Version 4.5 für x64-Architekturen. [ 3 ]
Diese Liste von Compilern [ 4 ] zeigt, dass die einzigen Compiler und Programmierumgebungen, die den OpenMP-Standard vollständig unterstützen, GCC und der Intel-Compiler sind. Tasks mit Abhängigkeiten (verfügbar seit OpenMP 4.0) sind nur in GCC, Intel Compiler, Oracle Compiler, PathScale Compiler, Cray Compiler, Clang, Parallware Suite, Mercurium und ARM Compiler verfügbar.
Siehe auch
- Parallelität (Informatik)
- Datenparallelität
- Aufgabenparallelität
- Laufzeitbibliothek
- Ausführung außer Betrieb
- parallele Programmierung
- OmpSs
- Cilk
- Intel-TBB
Verwandte Websites
Offizielle OpenMP-Site Archiviert am 20.07.2008 auf der Wayback Machine
Referenzen
- ↑ GNU. "GNU libgomp" (auf Englisch) . Abgerufen am 18. August 2017 .
- ↑ OpenMP Architecture Review Board. "Spezifikationen" (auf Englisch) . Abgerufen am 16. August 2017 .
- ↑ tim.lewis. „OpenMP-Compiler und -Tools“ . OpenMP (in britischem Englisch) . Abgerufen am 2. Juni 2022 .
- ↑ OpenMP Architecture Review Board. OpenMP- Compiler . Abgerufen am 16. August 2017 .