openmpErste Schritte mit openmp


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.

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.

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.