Share via


OpenMP-clausules

Biedt koppelingen naar componenten die worden gebruikt in de OpenMP-API.

Visual C++ ondersteunt de volgende OpenMP-componenten.

Voor algemene kenmerken:

Clausule Description
if Hiermee wordt aangegeven of een lus parallel of in serie moet worden uitgevoerd.
num_threads Hiermee stelt u het aantal threads in een threadteam in.
Besteld Vereist bij een parallelle for-constructie als een geordende instructie binnen de lus gebruikt moet worden.
planning Van toepassing op de for directive.
nowait Overschrijft de barrière die impliciet is in een richtlijn.

Voor kenmerken voor het delen van gegevens:

Clausule Description
privé Hiermee geeft u op dat elke thread een eigen exemplaar van een variabele moet hebben.
firstprivate Hiermee geeft u op dat elke thread een eigen exemplaar van een variabele moet hebben en dat de variabele moet worden geïnitialiseerd met de waarde van de variabele, omdat deze bestaat vóór de parallelle constructie.
lastprivate Hiermee geeft u op dat de versie van de variabele binnen de omringende context gelijk is aan de eigen versie van de thread die de finale iteratie (for-loop construct) of laatste sectie (#pragma secties) uitvoert.
gedeelde Hiermee geeft u op dat een of meer variabelen moeten worden gedeeld tussen alle threads.
default Hiermee geeft u het gedrag van niet-gescoopte variabelen in een parallelle regio.
reductie Hiermee geeft u op dat een of meer variabelen die privé zijn voor elke thread, het onderwerp zijn van een reductiebewerking aan het einde van de parallelle regio.
kopiëren Hiermee hebben threads toegang tot de waarde van de hoofdthread voor een threadprivate-variabele .
copyprivate Hiermee geeft u op dat een of meer variabelen moeten worden gedeeld tussen alle threads.

kopiëren

Hiermee hebben threads toegang tot de waarde van de hoofdthread voor een threadprivate-variabele .

copyin(var)

Parameterwaarden

var
De threadprivate variabele die wordt geïnitialiseerd met de waarde van de variabele in de hoofdthread, zoals deze bestaat vóór de parallelle constructie.

Opmerkingen

copyin is van toepassing op de volgende richtlijnen:

Zie 2.7.2.7 copyin voor meer informatie.

Example

Zie threadprivate voor een voorbeeld van het gebruik copyin.

copyprivate

Hiermee geeft u op dat een of meer variabelen moeten worden gedeeld tussen alle threads.

copyprivate(var)

Parameterwaarden

var
Een of meer variabelen die u wilt delen. Als er meer dan één variabele is opgegeven, scheidt u de namen van variabelen met een komma.

Opmerkingen

copyprivate is van toepassing op de ene richtlijn.

Zie 2.7.2.8 copyprivate voor meer informatie.

Example

// 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

standaard

Hiermee geeft u het gedrag van niet-gescoopte variabelen in een parallelle regio.

default(shared | none)

Opmerkingen

shared, dat van kracht is als de default component niet is opgegeven, betekent dat elke variabele in een parallelle regio wordt behandeld alsof deze is opgegeven met de gedeelde component. nonebetekent dat variabelen die worden gebruikt in een parallelle regio die niet onder het bereik vallen van de private, shared, reduction, firstprivate-, of lastprivate-clausule een compilerfout veroorzaken.

default is van toepassing op de volgende richtlijnen:

Zie de standaardwaarde 2.7.2.5 voor meer informatie.

Example

Zie privé voor een voorbeeld van het gebruik default.

firstprivate

Hiermee geeft u op dat elke thread een eigen exemplaar van een variabele moet hebben en dat de variabele moet worden geïnitialiseerd met de waarde van de variabele, omdat deze bestaat vóór de parallelle constructie.

firstprivate(var)

Parameterwaarden

var
De variabele moet in elke thread instanties hebben en zal worden geïnitialiseerd met de waarde van de variabele, omdat deze al bestaat vóór de parallelle constructie. Als er meer dan één variabele is opgegeven, scheidt u de namen van variabelen met een komma.

Opmerkingen

firstprivate is van toepassing op de volgende richtlijnen:

Zie 2.7.2.2.2 firstprivate voor meer informatie.

Example

Zie het voorbeeld in firstprivate voor een voorbeeld van het gebruik.

if (OpenMP)

Hiermee wordt aangegeven of een lus parallel of in serie moet worden uitgevoerd.

if(expression)

Parameterwaarden

expressie
Een integrale expressie die, als deze resulteert in waar (nietzero), zorgt ervoor dat de code in de parallelle regio parallel wordt uitgevoerd. Als de uitdrukking onwaar (nul) evalueert, wordt de parallelle regio in seriële modus uitgevoerd (door een enkele draad).

Opmerkingen

if is van toepassing op de volgende richtlijnen:

Zie 2.3 parallel construct voor meer informatie.

Example

// 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

Hiermee geeft u op dat de versie van de variabele binnen de omringende context gelijk is aan de eigen versie van de thread die de finale iteratie (for-loop construct) of laatste sectie (#pragma secties) uitvoert.

lastprivate(var)

Parameterwaarden

var
De variabele die gelijk is gesteld aan de privéversie van welke thread dan ook die de laatste iteratie (for-loop-construct) of laatste sectie (#pragma secties) uitvoert.

Opmerkingen

lastprivate is van toepassing op de volgende richtlijnen:

Zie 2.7.2.3 lastprivate voor meer informatie.

Example

Zie het schema voor een voorbeeld van het gebruik van een lastprivate clausule.

nowait

Overschrijft de barrière die impliciet is in een richtlijn.

nowait

Opmerkingen

nowait is van toepassing op de volgende richtlijnen:

Zie 2.4.1 voor constructie, 2.4.2 secties en2.4.3 enkele constructie voor meer informatie.

Example

// 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

Hiermee stelt u het aantal threads in een threadteam in.

num_threads(num)

Parameterwaarden

Nummer
Het aantal threads

Opmerkingen

De num_threads component heeft dezelfde functionaliteit als de functie omp_set_num_threads .

num_threads is van toepassing op de volgende richtlijnen:

Zie 2.3 parallel construct voor meer informatie.

Example

Zie parallel voor een voorbeeld van het gebruik van num_threads.

Besteld

Vereist bij een parallelle for-constructie als een geordende instructie binnen de lus gebruikt moet worden.

ordered

Opmerkingen

ordered is van toepassing op de richtlijn for.

Zie 2.4.1 voor meer informatie voor constructie.

Example

Zie geordend voor een voorbeeld van het gebruik ordered van een clausule.

privé

Hiermee geeft u op dat elke thread een eigen exemplaar van een variabele moet hebben.

private(var)

Parameterwaarden

var
De variabele moet instanties hebben in elke thread.

Opmerkingen

private is van toepassing op de volgende richtlijnen:

Zie 2.7.2.1 privé voor meer informatie.

Example

// 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)

Vermindering

Hiermee geeft u op dat een of meer variabelen die privé zijn voor elke thread, het onderwerp zijn van een reductiebewerking aan het einde van de parallelle regio.

reduction(operation:var)

Parameterwaarden

operatie
De operator voor de bewerking die moet worden uitgevoerd op de variabelen var aan het einde van de parallelle regio.

var
Een of meer variabelen waarop scalaire reductie moet worden uitgevoerd. Als er meer dan één variabele is opgegeven, scheidt u de namen van variabelen met een komma.

Opmerkingen

reduction is van toepassing op de volgende richtlijnen:

Zie 2.7.2.6 reductie voor meer informatie.

Example

// 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

Van toepassing op de for directive.

schedule(type[,size])

Parameterwaarden

type
Het soort planning, ofwel dynamic, guided, runtime, of static.

grootte
(Optioneel) Hiermee geeft u de grootte van iteraties. de grootte moet een geheel getal zijn. Niet geldig wanneer type is runtime.

Opmerkingen

Zie 2.4.1 voor meer informatie voor constructie.

Example

// 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   |
------------------------------------------------

gedeeld

Hiermee geeft u op dat een of meer variabelen moeten worden gedeeld tussen alle threads.

shared(var)

Parameterwaarden

var
Een of meer variabelen die u wilt delen. Als er meer dan één variabele is opgegeven, scheidt u de namen van variabelen met een komma.

Opmerkingen

Een andere manier om variabelen tussen threads te delen, is met de copyprivate-component .

shared is van toepassing op de volgende richtlijnen:

Zie 2.7.2.4 gedeeld voor meer informatie.

Example

Zie privé voor een voorbeeld van het gebruik shared.