openmp Tutorial
Erste Schritte mit openmp
Suche…
Bemerkungen
OpenMP (Open MultiProcessing) ist ein paralleles Programmiermodell, das auf Compiler-Direktiven basiert und Anwendungsentwicklern die Möglichkeit gibt, inkrementell Parallelität zu ihren Anwendungscodes hinzuzufügen.
Die OpenMP-API-Spezifikation für die parallele Programmierung bietet eine Anwendungsprogrammierschnittstelle (Application Programming Interface, API), die die Multiprocessing-Programmierung für mehrere Plattformen mit gemeinsamem Speicher in C, C ++ und Fortran auf den meisten Plattformen unterstützt. Es besteht aus einer Reihe von Compiler-Direktiven, Bibliotheksroutinen und Umgebungsvariablen, die das Laufzeitverhalten beeinflussen.
Da sich OpenMP auf die Parallelität innerhalb eines Knotens konzentriert (Shared Memory Multiprocessing), kann es mit Message-Passing-Programmiermodellen wie MPI kombiniert werden, um es auf mehreren Knoten auszuführen.
Versionen
Ausführung | Sprache | Veröffentlichungsdatum |
---|---|---|
4,5 | C / C ++ / Fortran | 2015-11-01 |
4,0 | C / C ++ / Fortran | 2013-07-01 |
3.1 | C / C ++ / Fortran | 2011-07-01 |
3,0 | C / C ++ / Fortran | 2008-05-01 |
2,5 | C / C ++ / Fortran | 2005-05-01 |
2.0c | C / C ++ | 2002-03-01 |
2.0f | Fortran | 2000-11-01 |
1,0c | C / C ++ | 1998-10-01 |
1,0f | Fortran | 1997-10-01 |
Zusammenstellung
Es gibt viele Compiler, die verschiedene Versionen der OpenMP-Spezifikation unterstützen. OpenMP führt eine Liste hier mit dem Compiler , dass es und der unterstützten Version unterstützen. Um eine Anwendung mit OpenMP-Unterstützung zu kompilieren (und zu verknüpfen), müssen Sie im Allgemeinen nur ein Kompilierungsflag hinzufügen. Wenn Sie die OpenMP-API verwenden, müssen Sie den OpenMP-Header (omp.h) einfügen. Während die Header-Datei einen festen Namen hat, hängt das Compile-Flag vom Compiler ab. Das Folgende ist eine nicht erschöpfende Liste von Compilern und das Flag, das OpenMP aktiviert.
- GCC (einschließlich gcc, g ++ und gfortran):
-fopenmp
- LLVM: -fopenmp
- Intel Compiler-Suite (einschließlich icc, icpc und ifort):
-qopenmp
(und-fopenmp
für Kompatibilität mit GCC / LLVM) - IBM XL Compiler-Suite (einschließlich xlc, xlC und xlf):
-xlsmp=omp
- PGI-Compiler-Suite (einschließlich pgcc pgc ++ pgfortran): '-mp'
Parallele Hallo Welt mit OpenMP
#include <omp.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
#pragma omp parallel
{
printf ("Hello world! I'm thread %d out of %d threads.\n",
omp_get_thread_num(), omp_get_num_threads());
}
return 0;
}
Dieser Code erstellt einfach ein Team von Threads (entsprechend der Umgebungsvariablen OMP_NUM_THREADS
- und wenn nicht definiert, wird pro logischem Kern auf dem System ein OMP_NUM_THREADS
erstellt), und jeder Thread identifiziert sich neben dem Drucken der typischen Hello-World-Nachricht.
Work Sharing-Konstrukt - Beispiel für eine For-Schleife
double res[MAX]; int i;
#pragma omp parallel
{
#pragma omp for
for (i=0;i< MAX; i++) {
res[i] = huge();
}
}
Die for-Schleife wird parallel ausgeführt. riesige () ist eine Methode, deren Ausführung zu lange dauern kann. OpenMP unterstützt eine Verknüpfung zum Schreiben des obigen Codes als:
double res[MAX]; int i;
#pragma omp parallel for
for (i=0;i< MAX; i++) {
res[i] = huge();
}
Wir können auch eine Zeitplanklausel haben, die bewirkt, wie Schleifeniterationen Threads zugeordnet werden. Zum Beispiel:
#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;I<N;i++) {
a[i] = a[i] + b[i];
}
Unterschiedliche Planungsstile sind:
Zeitplan (statisch [, Stück])
Verteilen Sie Blöcke mit Iterationen der Größe "Chunk" an jeden Thread.
Wenn nicht angegeben: Weisen Sie den verfügbaren Threads möglichst gleichmäßig zu
Zeitplan (dynamisch [, Stück])
Jeder Thread holt sich "Chunk" -Iterationen aus einer Warteschlange, bis alle Iterationen verarbeitet wurden.
Zeitplan (geführt [, Stück])
Threads greifen dynamisch Blöcke von Iterationen auf. Die Größe des Blocks beginnt groß und verkleinert sich mit der Berechnung auf einen "Block".
Zeitplan (Laufzeit)
Zeitplan und Blockgröße werden aus der Umgebungsvariablen OMP_SCHEDULE übernommen.
Reduktionsbeispiel
#include <omp.h>
void main ()
{
int i;
double ZZ, func(), res=0.0;
#pragma omp parallel for reduction(+:res) private(ZZ)
for (i=0; i< 1000; i++){
ZZ = func(I);
res = res + ZZ;
}
}
In der letzten Zeile: Wird tatsächlich zu einer privaten Kopie hinzugefügt und dann nach der Schleife kombiniert. Der Compiler kümmert sich um die Details.