Teilen über


OpenMP-Direktiven

Stellt Links zu Direktiven bereit, die in der OpenMP-API verwendet werden.

Visual C++ unterstützt die folgenden OpenMP-Direktiven.

Für parallele Arbeitsfreigabe:

Anweisung Beschreibung
parallel Definiert einen parallelen Bereich, der Code ist, der von mehreren Threads parallel ausgeführt wird.
for Bewirkt, dass die Arbeit in einer for Schleife innerhalb eines parallelen Bereichs in Threads aufgeteilt wird.
sections Identifiziert Codeabschnitte, die in alle Threads unterteilt werden sollen.
single Hiermit können Sie angeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, nicht unbedingt der Hauptthread.

Für Hauptthread und Synchronisierung:

Anweisung Beschreibung
master Gibt an, dass nur der Hauptthread einen Abschnitt des Programms ausführen soll.
Kritisch Gibt an, dass Code nur jeweils auf einem Thread ausgeführt wird.
barrier Synchronisiert alle Threads in einem Team; Alle Threads halten an der Barriere an, bis alle Threads die Barriere ausführen.
atomic Gibt an, dass ein Speicherspeicherort, der atomisch aktualisiert wird.
flush Gibt an, dass alle Threads dieselbe Ansicht des Arbeitsspeichers für alle freigegebenen Objekte aufweisen.
angeordnet Gibt an, dass Code unter einer parallelisierten for Schleife wie eine sequenzielle Schleife ausgeführt werden soll.

Für Datenumgebung:

Anweisung Beschreibung
threadprivate Gibt an, dass eine Variable für einen Thread privat ist.

atomic

Gibt an, dass ein Speicherspeicherort, der atomisch aktualisiert wird.

#pragma omp atomic
   expression

Parameter

expression
Die Anweisung mit dem Wert "lvalue", deren Speicherspeicherort Sie vor mehreren Schreibvorgängen schützen möchten.

Hinweise

Die atomic Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie unter 2.6.4 Atomkonstrukt.

Beispiel

// omp_atomic.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

#define MAX 10

int main() {
   int count = 0;
   #pragma omp parallel num_threads(MAX)
   {
      #pragma omp atomic
      count++;
   }
   printf_s("Number of threads: %d\n", count);
}
Number of threads: 10

barrier

Synchronisiert alle Threads in einem Team; Alle Threads halten an der Barriere an, bis alle Threads die Barriere ausführen.

#pragma omp barrier

Hinweise

Die barrier Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie in der Barriererichtlinie 2.6.3.

Beispiel

Ein Beispiel für die Verwendung barrierfinden Sie unter Master.

Kritisch

Gibt an, dass Code nur auf einem Thread gleichzeitig ausgeführt wird.

#pragma omp critical [(name)]
{
   code_block
}

Parameter

name
(Optional) Ein Name zum Identifizieren des kritischen Codes. Der Name muss in Klammern eingeschlossen werden.

Hinweise

Die critical Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie im kritischen Konstrukt 2.6.2.

Beispiel

// omp_critical.cpp
// compile with: /openmp
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

int main()
{
    int i;
    int max;
    int a[SIZE];

    for (i = 0; i < SIZE; i++)
    {
        a[i] = rand();
        printf_s("%d\n", a[i]);
    }

    max = a[0];
    #pragma omp parallel for num_threads(4)
        for (i = 1; i < SIZE; i++)
        {
            if (a[i] > max)
            {
                #pragma omp critical
                {
                    // compare a[i] and max again because max
                    // could have been changed by another thread after
                    // the comparison outside the critical section
                    if (a[i] > max)
                        max = a[i];
                }
            }
        }

    printf_s("max = %d\n", max);
}
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
max = 29358

flush

Gibt an, dass alle Threads dieselbe Ansicht des Arbeitsspeichers für alle freigegebenen Objekte aufweisen.

#pragma omp flush [(var)]

Parameter

var
(Optional) Eine durch Trennzeichen getrennte Liste von Variablen, die Objekte darstellen, die Sie synchronisieren möchten. Wenn "var " nicht angegeben ist, wird der gesamte Arbeitsspeicher geleert.

Hinweise

Die flush Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie unter 2.6.5 Flush-Direktive.

Beispiel

// omp_flush.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

void read(int *data) {
   printf_s("read data\n");
   *data = 1;
}

void process(int *data) {
   printf_s("process data\n");
   (*data)++;
}

int main() {
   int data;
   int flag;

   flag = 0;

   #pragma omp parallel sections num_threads(2)
   {
      #pragma omp section
      {
         printf_s("Thread %d: ", omp_get_thread_num( ));
         read(&data);
         #pragma omp flush(data)
         flag = 1;
         #pragma omp flush(flag)
         // Do more work.
      }

      #pragma omp section
      {
         while (!flag) {
            #pragma omp flush(flag)
         }
         #pragma omp flush(data)

         printf_s("Thread %d: ", omp_get_thread_num( ));
         process(&data);
         printf_s("data = %d\n", data);
      }
   }
}
Thread 0: read data
Thread 1: process data
data = 2

für

Bewirkt, dass die Arbeit in einer for Schleife innerhalb eines parallelen Bereichs in Threads aufgeteilt wird.

#pragma omp [parallel] for [clauses]
   for_statement

Parameter

klauseln
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".

for_statement
Eine for Schleife. Das nicht definierte Verhalten führt dazu, dass der Benutzercode in der for Schleife die Indexvariable ändert.

Hinweise

Die for Direktive unterstützt die folgenden Klauseln:

Wenn parallel auch angegeben, kann eine beliebige Klausel sein, clauses die von den parallel Richtlinien for akzeptiert wird, außer nowait.

Weitere Informationen finden Sie unter 2.4.1 für das Konstrukt.

Beispiel

// omp_for.cpp
// compile with: /openmp
#include <stdio.h>
#include <math.h>
#include <omp.h>

#define NUM_THREADS 4
#define NUM_START 1
#define NUM_END 10

int main() {
   int i, nRet = 0, nSum = 0, nStart = NUM_START, nEnd = NUM_END;
   int nThreads = 0, nTmp = nStart + nEnd;
   unsigned uTmp = (unsigned((abs(nStart - nEnd) + 1)) *
                               unsigned(abs(nTmp))) / 2;
   int nSumCalc = uTmp;

   if (nTmp < 0)
      nSumCalc = -nSumCalc;

   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel default(none) private(i) shared(nSum, nThreads, nStart, nEnd)
   {
      #pragma omp master
      nThreads = omp_get_num_threads();

      #pragma omp for
      for (i=nStart; i<=nEnd; ++i) {
            #pragma omp atomic
            nSum += i;
      }
   }

   if  (nThreads == NUM_THREADS) {
      printf_s("%d OpenMP threads were used.\n", NUM_THREADS);
      nRet = 0;
   }
   else {
      printf_s("Expected %d OpenMP threads, but %d were used.\n",
               NUM_THREADS, nThreads);
      nRet = 1;
   }

   if (nSum != nSumCalc) {
      printf_s("The sum of %d through %d should be %d, "
               "but %d was reported!\n",
               NUM_START, NUM_END, nSumCalc, nSum);
      nRet = 1;
   }
   else
      printf_s("The sum of %d through %d is %d\n",
               NUM_START, NUM_END, nSum);
}
4 OpenMP threads were used.
The sum of 1 through 10 is 55

master

Gibt an, dass nur der Hauptthread einen Abschnitt des Programms ausführen soll.

#pragma omp master
{
   code_block
}

Hinweise

Die master Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie unter 2.6.1 Master-Konstrukt.

Um anzugeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, verwenden Sie stattdessen die einzelne Direktive, nicht unbedingt den Hauptthread.

Beispiel

// compile with: /openmp
#include <omp.h>
#include <stdio.h>

int main( )
{
    int a[5], i;

    #pragma omp parallel
    {
        // Perform some computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] = i * i;

        // Print intermediate results.
        #pragma omp master
            for (i = 0; i < 5; i++)
                printf_s("a[%d] = %d\n", i, a[i]);

        // Wait.
        #pragma omp barrier

        // Continue with the computation.
        #pragma omp for
        for (i = 0; i < 5; i++)
            a[i] += i;
    }
}
a[0] = 0
a[1] = 1
a[2] = 4
a[3] = 9
a[4] = 16

geordnete

Gibt an, dass Code unter einer parallelisierten for Schleife wie eine sequenzielle Schleife ausgeführt werden soll.

#pragma omp ordered
   structured-block

Hinweise

Die ordered Richtlinie muss sich innerhalb des dynamischen Umfangs eines For- oder parallel for Konstruierens mit einer ordered Klausel belassen.

Die ordered Direktive unterstützt keine Klauseln.

Weitere Informationen finden Sie unter 2.6.6 geordnetes Konstrukt.

Beispiel

// omp_ordered.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

static float a[1000], b[1000], c[1000];

void test(int first, int last)
{
    #pragma omp for schedule(static) ordered
    for (int i = first; i <= last; ++i) {
        // Do something here.
        if (i % 2)
        {
            #pragma omp ordered
            printf_s("test() iteration %d\n", i);
        }
    }
}

void test2(int iter)
{
    #pragma omp ordered
    printf_s("test2() iteration %d\n", iter);
}

int main( )
{
    int i;
    #pragma omp parallel
    {
        test(1, 8);
        #pragma omp for ordered
        for (i = 0 ; i < 5 ; i++)
            test2(i);
    }
}
test() iteration 1
test() iteration 3
test() iteration 5
test() iteration 7
test2() iteration 0
test2() iteration 1
test2() iteration 2
test2() iteration 3
test2() iteration 4

parallel

Definiert einen parallelen Bereich, der Code ist, der von mehreren Threads parallel ausgeführt wird.

#pragma omp parallel [clauses]
{
   code_block
}

Parameter

klauseln
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".

Hinweise

Die parallel Direktive unterstützt die folgenden Klauseln:

parallel kann auch mit den Für - und Abschnittsdirektiven verwendet werden.

Weitere Informationen finden Sie unter 2.3 paralleles Konstrukt.

Beispiel

Das folgende Beispiel zeigt, wie Sie die Anzahl der Threads festlegen und einen parallelen Bereich definieren. Die Anzahl der Threads entspricht standardmäßig der Anzahl der logischen Prozessoren auf dem Computer. Wenn Sie z. B. einen Computer mit einem physischen Prozessor haben, der Hyperthreading aktiviert hat, verfügen sie über zwei logische Prozessoren und zwei Threads. Die Ausgabereihenfolge kann auf verschiedenen Computern variieren.

// omp_parallel.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int main() {
   #pragma omp parallel num_threads(4)
   {
      int i = omp_get_thread_num();
      printf_s("Hello from thread %d\n", i);
   }
}
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

sections

Identifiziert Codeabschnitte, die in alle Threads unterteilt werden sollen.

#pragma omp [parallel] sections [clauses]
{
   #pragma omp section
   {
      code_block
   }
}

Parameter

klauseln
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".

Hinweise

Die sections Direktive kann null oder mehr section Direktiven enthalten.

Die sections Direktive unterstützt die folgenden Klauseln:

Wenn parallel auch angegeben, kann eine beliebige Klausel sein, clauses die von den parallel Richtlinien sections akzeptiert wird, außer nowait.

Weitere Informationen finden Sie im Abschnittskonstrukt 2.4.2.

Beispiel

// omp_sections.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int main() {
    #pragma omp parallel sections num_threads(4)
    {
        printf_s("Hello from thread %d\n", omp_get_thread_num());
        #pragma omp section
        printf_s("Hello from thread %d\n", omp_get_thread_num());
    }
}
Hello from thread 0
Hello from thread 0

single

Hiermit können Sie angeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, nicht unbedingt der Hauptthread.

#pragma omp single [clauses]
{
   code_block
}

Parameter

klauseln
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".

Hinweise

Die single Direktive unterstützt die folgenden Klauseln:

Weitere Informationen finden Sie unter 2.4.3 single construct.

Um anzugeben, dass ein Codeabschnitt nur im Hauptthread ausgeführt werden soll, verwenden Sie stattdessen die Masterdirektive .

Beispiel

// omp_single.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

int main() {
   #pragma omp parallel num_threads(2)
   {
      #pragma omp single
      // Only a single thread can read the input.
      printf_s("read input\n");

      // Multiple threads in the team compute the results.
      printf_s("compute results\n");

      #pragma omp single
      // Only a single thread can write the output.
      printf_s("write output\n");
    }
}
read input
compute results
compute results
write output

threadprivate

Gibt an, dass eine Variable für einen Thread privat ist.

#pragma omp threadprivate(var)

Parameter

var
Eine durch Trennzeichen getrennte Liste von Variablen, die Sie als privat für einen Thread festlegen möchten. var muss entweder eine globale oder namespacebezogene Variable oder eine lokale statische Variable sein.

Hinweise

Die threadprivate Direktive unterstützt keine Klauseln.

Die threadprivate Direktive basiert auf dem Thread-Attribut mit dem schlüsselwort __declspec ; limits on __declspec(thread) apply to threadprivate. Beispielsweise ist eine threadprivate Variable in jedem Thread vorhanden, der im Prozess gestartet wurde, nicht nur in den Threads, die Teil eines Threadteams sind, der von einem parallelen Bereich bereitgestellt wird. Seien Sie sich dieser Implementierungsdetails bewusst; Möglicherweise stellen Sie fest, dass Konstruktoren für einen threadprivate benutzerdefinierten Typ häufiger als erwartet bezeichnet werden.

Sie können in einer DLL verwenden threadprivate , die beim Prozessstart statisch geladen wird. Sie können jedoch keine DLL verwenden threadprivate , die über LoadLibrary geladen wird, z. B. DLLs, die mit /DELAYLOAD (Verzögerungsladeimport) geladen werden, die ebenfalls verwendet LoadLibrarywerden.

Eine threadprivate Variable eines destruktierbaren Typs ist nicht garantiert, dass der Destruktor aufgerufen wird. Zum Beispiel:

struct MyType
{
    ~MyType();
};

MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
    #pragma omp parallel
    {}
}

Benutzer haben keine Kontrolle darüber, wann die Threads, die den parallelen Bereich bilden, beendet werden. Wenn diese Threads vorhanden sind, wenn der Prozess beendet wird, werden die Threads nicht über den Prozessende benachrichtigt, und der Destruktor wird für keinen Thread aufgerufen threaded_var , außer für den Thread, der beendet wird (hier der primäre Thread). Daher sollte code nicht auf die ordnungsgemäße Zerstörung von threadprivate Variablen zählen.

Weitere Informationen finden Sie unter der Threadprivate-Direktive 2.7.1.

Beispiel

Ein Beispiel für die Verwendung threadprivatefinden Sie unter "Privat".