Freigeben über


OpenMP-Klauseln

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

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

Für allgemeine Attribute:

Klausel Beschreibung
if Gibt an, ob eine Schleife parallel oder serial ausgeführt werden soll.
num_threads Legt die Anzahl der Threads in einem Threadteam fest.
angeordnet Erforderlich für eine parallele Anweisung , wenn eine geordnete Direktive in der Schleife verwendet werden soll.
schedule Gilt für die Direktive .
nowait Überschreibt die in einer Direktive implizite Barriere.

Für Datenfreigabeattribute:

Klausel Beschreibung
private Gibt an, dass jeder Thread über eine eigene Instanz einer Variablen verfügen soll.
firstprivate Gibt an, dass jeder Thread eine eigene Instanz einer Variablen haben soll und dass die Variable mit dem Wert der Variablen initialisiert werden soll, da sie vor dem parallelen Konstrukt vorhanden ist.
lastprivate Gibt an, dass die Version des eingeschlossenen Kontexts der Variablen auf die private Version des Threads festgelegt wird, für die der letzte Iteration (for-loop-Konstrukt) oder der letzte Abschnitt (#pragma Abschnitte) ausgeführt wird.
geteilt Gibt an, dass eine oder mehrere Variablen für alle Threads freigegeben werden sollen.
default Gibt das Verhalten von nicht bereichsierten Variablen in einem parallelen Bereich an.
reduction Gibt an, dass mindestens eine Variable, die für jeden Thread privat ist, das Thema eines Reduzierungsvorgangs am Ende des parallelen Bereichs ist.
copyin Ermöglicht Threads den Zugriff auf den Wert des Hauptthreads für eine Threadprivate-Variable .
copyprivate Gibt an, dass eine oder mehrere Variablen für alle Threads freigegeben werden sollen.

copyin

Ermöglicht Threads den Zugriff auf den Wert des Hauptthreads für eine Threadprivate-Variable .

copyin(var)

Parameter

var
Die threadprivate Variable, die mit dem Wert der Variablen im Hauptthread initialisiert wird, wie sie vor dem parallelen Konstrukt vorhanden ist.

Hinweise

copyin gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.7 copyin.

Beispiel

Ein Beispiel für die Verwendung copyinfinden Sie unter threadprivate .

copyprivate

Gibt an, dass eine oder mehrere Variablen für alle Threads freigegeben werden sollen.

copyprivate(var)

Parameter

var
Mindestens eine Variable, die freigegeben werden soll. Wenn mehrere Variablen angegeben werden, trennen Sie Variablennamen mit einem Komma.

Hinweise

copyprivate gilt für die einheitliche Richtlinie.

Weitere Informationen finden Sie unter 2.7.2.8 copyprivate.

Beispiel

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

float x, y, fGlobal = 1.0;
#pragma omp threadprivate(x, y)

float get_float() {
   fGlobal += 0.001;
   return fGlobal;
}

void use_float(float f, int t) {
   printf_s("Value = %f, thread = %d\n", f, t);
}

void CopyPrivate(float a, float b) {
   #pragma omp single copyprivate(a, b, x, y)
   {
      a = get_float();
      b = get_float();
      x = get_float();
      y = get_float();
    }

   use_float(a, omp_get_thread_num());
   use_float(b, omp_get_thread_num());
   use_float(x, omp_get_thread_num());
   use_float(y, omp_get_thread_num());
}

int main() {
   float a = 9.99, b = 123.456;

   printf_s("call CopyPrivate from a single thread\n");
   CopyPrivate(9.99, 123.456);

   printf_s("call CopyPrivate from a parallel region\n");
   #pragma omp parallel
   {
      CopyPrivate(a, b);
   }
}
call CopyPrivate from a single thread
Value = 1.001000, thread = 0
Value = 1.002000, thread = 0
Value = 1.003000, thread = 0
Value = 1.004000, thread = 0
call CopyPrivate from a parallel region
Value = 1.005000, thread = 0
Value = 1.005000, thread = 1
Value = 1.006000, thread = 0
Value = 1.006000, thread = 1
Value = 1.007000, thread = 0
Value = 1.007000, thread = 1
Value = 1.008000, thread = 0
Value = 1.008000, thread = 1

default

Gibt das Verhalten von nicht bereichsierten Variablen in einem parallelen Bereich an.

default(shared | none)

Hinweise

shared, was in Kraft ist, wenn die default Klausel nicht angegeben ist, bedeutet, dass jede Variable in einem parallelen Bereich so behandelt wird, als ob sie mit der freigegebenen Klausel angegeben wurde. nonebedeutet, dass alle variablen, die in einem parallelen Bereich verwendet werden, die nicht auf den Bereich private, freigegebene, reduktion, firstprivate oder lastprivate-Klausel festgelegt sind, einen Compilerfehler verursachen.

default gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.5 Standard.

Beispiel

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

firstprivate

Gibt an, dass jeder Thread eine eigene Instanz einer Variablen haben soll und dass die Variable mit dem Wert der Variablen initialisiert werden soll, da sie vor dem parallelen Konstrukt vorhanden ist.

firstprivate(var)

Parameter

var
Die Variable, die Instanzen in jedem Thread enthalten soll und die mit dem Wert der Variablen initialisiert werden, da sie vor dem parallelen Konstrukt vorhanden ist. Wenn mehrere Variablen angegeben werden, trennen Sie Variablennamen mit einem Komma.

Hinweise

firstprivate gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.2 firstprivate.

Beispiel

Ein Beispiel für die Verwendung firstprivatefinden Sie im Beispiel in "Privat".

if (OpenMP)

Gibt an, ob eine Schleife parallel oder serial ausgeführt werden soll.

if(expression)

Parameter

expression
Ein integraler Ausdruck, der, wenn er als wahr ausgewertet wird (nonzero), bewirkt, dass der Code im parallelen Bereich parallel ausgeführt wird. Wenn der Ausdruck auf "false" (Null) ausgewertet wird, wird der parallele Bereich in der seriellen Ausführung (durch einen einzelnen Thread) ausgeführt.

Hinweise

if gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.3 paralleles Konstrukt.

Beispiel

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

void test(int val)
{
    #pragma omp parallel if (val)
    if (omp_in_parallel())
    {
        #pragma omp single
        printf_s("val = %d, parallelized with %d threads\n",
                 val, omp_get_num_threads());
    }
    else
    {
        printf_s("val = %d, serialized\n", val);
    }
}

int main( )
{
    omp_set_num_threads(2);
    test(0);
    test(2);
}
val = 0, serialized
val = 2, parallelized with 2 threads

lastprivate

Gibt an, dass die Version des eingeschlossenen Kontexts der Variablen auf die private Version des Threads festgelegt wird, für die der letzte Iteration (for-loop-Konstrukt) oder der letzte Abschnitt (#pragma Abschnitte) ausgeführt wird.

lastprivate(var)

Parameter

var
Die Variable, die auf die private Version des Threads festgelegt ist, führt die endgültige Iteration (For-Loop-Konstrukt) oder den letzten Abschnitt (#pragma Abschnitte) aus.

Hinweise

lastprivate gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.3 lastprivate.

Beispiel

Ein Beispiel für die Verwendung lastprivate von Klauseln finden Sie im Zeitplan.

nowait

Überschreibt die in einer Direktive implizite Barriere.

nowait

Hinweise

nowait gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.4.1 für Konstrukte, 2.4.2-Abschnitte und 2.4.3 einzelnes Konstrukt.

Beispiel

// omp_nowait.cpp
// compile with: /openmp /c
#include <stdio.h>

#define SIZE 5

void test(int *a, int *b, int *c, int size)
{
    int i;
    #pragma omp parallel
    {
        #pragma omp for nowait
        for (i = 0; i < size; i++)
            b[i] = a[i] * a[i];

        #pragma omp for nowait
        for (i = 0; i < size; i++)
            c[i] = a[i]/2;
    }
}

int main( )
{
    int a[SIZE], b[SIZE], c[SIZE];
    int i;

    for (i=0; i<SIZE; i++)
        a[i] = i;

    test(a,b,c, SIZE);

    for (i=0; i<SIZE; i++)
        printf_s("%d, %d, %d\n", a[i], b[i], c[i]);
}
0, 0, 0
1, 1, 0
2, 4, 1
3, 9, 1
4, 16, 2

num_threads

Legt die Anzahl der Threads in einem Threadteam fest.

num_threads(num)

Parameter

num
Die Anzahl der Threads

Hinweise

Die num_threads Klausel weist die gleiche Funktionalität wie die omp_set_num_threads-Funktion auf.

num_threads gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.3 paralleles Konstrukt.

Beispiel

Ein Beispiel für die Verwendung num_threads von Klauseln finden Sie parallel.

geordnete

Erforderlich für eine parallele Anweisung , wenn eine geordnete Direktive in der Schleife verwendet werden soll.

ordered

Hinweise

ordered gilt für die Richtlinie .

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

Beispiel

Ein Beispiel für die Verwendungsklausel ordered finden Sie unter "Sortiert".

private

Gibt an, dass jeder Thread über eine eigene Instanz einer Variablen verfügen soll.

private(var)

Parameter

var
Die Variable, die Instanzen in jedem Thread enthalten soll.

Hinweise

private gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.1 privat.

Beispiel

// openmp_private.c
// compile with: /openmp
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <omp.h>

#define NUM_THREADS 4
#define SLEEP_THREAD 1
#define NUM_LOOPS 2

enum Types {
   ThreadPrivate,
   Private,
   FirstPrivate,
   LastPrivate,
   Shared,
   MAX_TYPES
};

int nSave[NUM_THREADS][MAX_TYPES][NUM_LOOPS] = {{0}};
int nThreadPrivate;

#pragma omp threadprivate(nThreadPrivate)
#pragma warning(disable:4700)

int main() {
   int nPrivate = NUM_THREADS;
   int nFirstPrivate = NUM_THREADS;
   int nLastPrivate = NUM_THREADS;
   int nShared = NUM_THREADS;
   int nRet = 0;
   int i;
   int j;
   int nLoop = 0;

   nThreadPrivate = NUM_THREADS;
   printf_s("These are the variables before entry "
           "into the parallel region.\n");
   printf_s("nThreadPrivate = %d\n", nThreadPrivate);
   printf_s("      nPrivate = %d\n", nPrivate);
   printf_s(" nFirstPrivate = %d\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d\n", nLastPrivate);
   printf_s("       nShared = %d\n\n", nShared);
   omp_set_num_threads(NUM_THREADS);

   #pragma omp parallel copyin(nThreadPrivate) private(nPrivate) shared(nShared) firstprivate(nFirstPrivate)
   {
      #pragma omp for schedule(static) lastprivate(nLastPrivate)
      for (i = 0 ; i < NUM_THREADS ; ++i) {
         for (j = 0 ; j < NUM_LOOPS ; ++j) {
            int nThread = omp_get_thread_num();
            assert(nThread < NUM_THREADS);

            if (nThread == SLEEP_THREAD)
               Sleep(100);
            nSave[nThread][ThreadPrivate][j] = nThreadPrivate;
            nSave[nThread][Private][j] = nPrivate;
            nSave[nThread][Shared][j] = nShared;
            nSave[nThread][FirstPrivate][j] = nFirstPrivate;
            nSave[nThread][LastPrivate][j] = nLastPrivate;
            nThreadPrivate = nThread;
            nPrivate = nThread;
            nShared = nThread;
            nLastPrivate = nThread;
            --nFirstPrivate;
         }
      }
   }

   for (i = 0 ; i < NUM_LOOPS ; ++i) {
      for (j = 0 ; j < NUM_THREADS ; ++j) {
         printf_s("These are the variables at entry of "
                  "loop %d of thread %d.\n", i + 1, j);
         printf_s("nThreadPrivate = %d\n",
                  nSave[j][ThreadPrivate][i]);
         printf_s("      nPrivate = %d\n",
                  nSave[j][Private][i]);
         printf_s(" nFirstPrivate = %d\n",
                  nSave[j][FirstPrivate][i]);
         printf_s("  nLastPrivate = %d\n",
                  nSave[j][LastPrivate][i]);
         printf_s("       nShared = %d\n\n",
                  nSave[j][Shared][i]);
      }
   }

   printf_s("These are the variables after exit from "
            "the parallel region.\n");
   printf_s("nThreadPrivate = %d (The last value in the "
            "main thread)\n", nThreadPrivate);
   printf_s("      nPrivate = %d (The value prior to "
            "entering parallel region)\n", nPrivate);
   printf_s(" nFirstPrivate = %d (The value prior to "
            "entering parallel region)\n", nFirstPrivate);
   printf_s("  nLastPrivate = %d (The value from the "
            "last iteration of the loop)\n", nLastPrivate);
   printf_s("       nShared = %d (The value assigned, "
            "from the delayed thread, %d)\n\n",
            nShared, SLEEP_THREAD);
}
These are the variables before entry into the parallel region.
nThreadPrivate = 4
      nPrivate = 4
nFirstPrivate = 4
  nLastPrivate = 4
       nShared = 4

These are the variables at entry of loop 1 of thread 0.
nThreadPrivate = 4
      nPrivate = 1310720
nFirstPrivate = 4
  nLastPrivate = 1245104
       nShared = 3

These are the variables at entry of loop 1 of thread 1.
nThreadPrivate = 4
      nPrivate = 4488
nFirstPrivate = 4
  nLastPrivate = 19748
       nShared = 0

These are the variables at entry of loop 1 of thread 2.
nThreadPrivate = 4
      nPrivate = -132514848
nFirstPrivate = 4
  nLastPrivate = -513199792
       nShared = 4

These are the variables at entry of loop 1 of thread 3.
nThreadPrivate = 4
      nPrivate = 1206
nFirstPrivate = 4
  nLastPrivate = 1204
       nShared = 2

These are the variables at entry of loop 2 of thread 0.
nThreadPrivate = 0
      nPrivate = 0
nFirstPrivate = 3
  nLastPrivate = 0
       nShared = 0

These are the variables at entry of loop 2 of thread 1.
nThreadPrivate = 1
      nPrivate = 1
nFirstPrivate = 3
  nLastPrivate = 1
       nShared = 1

These are the variables at entry of loop 2 of thread 2.
nThreadPrivate = 2
      nPrivate = 2
nFirstPrivate = 3
  nLastPrivate = 2
       nShared = 2

These are the variables at entry of loop 2 of thread 3.
nThreadPrivate = 3
      nPrivate = 3
nFirstPrivate = 3
  nLastPrivate = 3
       nShared = 3

These are the variables after exit from the parallel region.
nThreadPrivate = 0 (The last value in the main thread)
      nPrivate = 4 (The value prior to entering parallel region)
nFirstPrivate = 4 (The value prior to entering parallel region)
  nLastPrivate = 3 (The value from the last iteration of the loop)
       nShared = 1 (The value assigned, from the delayed thread, 1)

reduction

Gibt an, dass mindestens eine Variable, die für jeden Thread privat ist, das Thema eines Reduzierungsvorgangs am Ende des parallelen Bereichs ist.

reduction(operation:var)

Parameter

operation
Der Operator für den Vorgang, der für die Variablen var am Ende des parallelen Bereichs ausgeführt werden soll.

var
Eine oder mehrere Variablen, für die skalare Reduzierung ausgeführt werden soll. Wenn mehrere Variablen angegeben werden, trennen Sie Variablennamen mit einem Komma.

Hinweise

reduction gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.6 Reduzierung.

Beispiel

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

#define NUM_THREADS 4
#define SUM_START   1
#define SUM_END     10
#define FUNC_RETS   {1, 1, 1, 1, 1}

int bRets[5] = FUNC_RETS;
int nSumCalc = ((SUM_START + SUM_END) * (SUM_END - SUM_START + 1)) / 2;

int func1( ) {return bRets[0];}
int func2( ) {return bRets[1];}
int func3( ) {return bRets[2];}
int func4( ) {return bRets[3];}
int func5( ) {return bRets[4];}

int main( )
{
    int nRet = 0,
        nCount = 0,
        nSum = 0,
        i,
        bSucceed = 1;

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel reduction(+ : nCount)
    {
        nCount += 1;

        #pragma omp for reduction(+ : nSum)
        for (i = SUM_START ; i <= SUM_END ; ++i)
            nSum += i;

        #pragma omp sections reduction(&& : bSucceed)
        {
            #pragma omp section
            {
                bSucceed = bSucceed && func1( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func2( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func3( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func4( );
            }

            #pragma omp section
            {
                bSucceed = bSucceed && func5( );
            }
        }
    }

    printf_s("The parallel section was executed %d times "
             "in parallel.\n", nCount);
    printf_s("The sum of the consecutive integers from "
             "%d to %d, is %d\n", 1, 10, nSum);

    if (bSucceed)
        printf_s("All of the functions, func1 through "
                 "func5 succeeded!\n");
    else
        printf_s("One or more of the functions, func1 "
                 "through func5 failed!\n");

    if (nCount != NUM_THREADS)
    {
        printf_s("ERROR: For %d threads, %d were counted!\n",
                 NUM_THREADS, nCount);
        nRet |= 0x1;
   }

    if (nSum != nSumCalc)
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                "but %d was reported!\n",
                SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x10;
    }

    if (bSucceed != (bRets[0] && bRets[1] &&
                     bRets[2] && bRets[3] && bRets[4]))
    {
        printf_s("ERROR: The sum of %d through %d should be %d, "
                 "but %d was reported!\n",
                 SUM_START, SUM_END, nSumCalc, nSum);
        nRet |= 0x100;
    }
}
The parallel section was executed 4 times in parallel.
The sum of the consecutive integers from 1 to 10, is 55
All of the functions, func1 through func5 succeeded!

schedule

Gilt für die Direktive .

schedule(type[,size])

Parameter

type
Die Art der Planung, entweder dynamic, , guided, runtimeoder static.

size
(Optional) Gibt die Größe der Iterationen an. Die Größe muss eine ganze Zahl sein. Ungültig, wenn der Typ ist runtime.

Hinweise

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

Beispiel

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

#define NUM_THREADS 4
#define STATIC_CHUNK 5
#define DYNAMIC_CHUNK 5
#define NUM_LOOPS 20
#define SLEEP_EVERY_N 3

int main( )
{
    int nStatic1[NUM_LOOPS],
        nStaticN[NUM_LOOPS];
    int nDynamic1[NUM_LOOPS],
        nDynamicN[NUM_LOOPS];
    int nGuided[NUM_LOOPS];

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel
    {
        #pragma omp for schedule(static, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStatic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(static, STATIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nStaticN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, 1)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamic1[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(dynamic, DYNAMIC_CHUNK)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nDynamicN[i] = omp_get_thread_num( );
        }

        #pragma omp for schedule(guided)
        for (int i = 0 ; i < NUM_LOOPS ; ++i)
        {
            if ((i % SLEEP_EVERY_N) == 0)
                Sleep(0);
            nGuided[i] = omp_get_thread_num( );
        }
    }

    printf_s("------------------------------------------------\n");
    printf_s("| static | static | dynamic | dynamic | guided |\n");
    printf_s("|    1   |    %d   |    1    |    %d    |        |\n",
             STATIC_CHUNK, DYNAMIC_CHUNK);
    printf_s("------------------------------------------------\n");

    for (int i=0; i<NUM_LOOPS; ++i)
    {
        printf_s("|    %d   |    %d   |    %d    |    %d    |"
                 "    %d   |\n",
                 nStatic1[i], nStaticN[i],
                 nDynamic1[i], nDynamicN[i], nGuided[i]);
    }

    printf_s("------------------------------------------------\n");
}
------------------------------------------------
| static | static | dynamic | dynamic | guided |
|    1   |    5   |    1    |    5    |        |
------------------------------------------------
|    0   |    0   |    0    |    2    |    1   |
|    1   |    0   |    3    |    2    |    1   |
|    2   |    0   |    3    |    2    |    1   |
|    3   |    0   |    3    |    2    |    1   |
|    0   |    0   |    2    |    2    |    1   |
|    1   |    1   |    2    |    3    |    3   |
|    2   |    1   |    2    |    3    |    3   |
|    3   |    1   |    0    |    3    |    3   |
|    0   |    1   |    0    |    3    |    3   |
|    1   |    1   |    0    |    3    |    2   |
|    2   |    2   |    1    |    0    |    2   |
|    3   |    2   |    1    |    0    |    2   |
|    0   |    2   |    1    |    0    |    3   |
|    1   |    2   |    2    |    0    |    3   |
|    2   |    2   |    2    |    0    |    0   |
|    3   |    3   |    2    |    1    |    0   |
|    0   |    3   |    3    |    1    |    1   |
|    1   |    3   |    3    |    1    |    1   |
|    2   |    3   |    3    |    1    |    1   |
|    3   |    3   |    0    |    1    |    3   |
------------------------------------------------

shared

Gibt an, dass eine oder mehrere Variablen für alle Threads freigegeben werden sollen.

shared(var)

Parameter

var
Mindestens eine Variable, die freigegeben werden soll. Wenn mehrere Variablen angegeben werden, trennen Sie Variablennamen mit einem Komma.

Hinweise

Eine weitere Möglichkeit zum Freigeben von Variablen zwischen Threads ist die CopyPrivate-Klausel .

shared gilt für die folgenden Richtlinien:

Weitere Informationen finden Sie unter 2.7.2.4 freigegeben.

Beispiel

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