Dela via


OpenMP Directives

Innehåller länkar till direktiv som används i OpenMP-API:et.

Visual C++ stöder följande OpenMP-direktiv.

För parallell arbetsdelning:

Directive Description
parallel Definierar en parallell region, som är kod som ska köras av flera trådar parallellt.
for Gör att arbetet som utförs i en for loop i en parallell region delas upp mellan trådar.
sections Identifierar kodavsnitt som ska delas upp mellan alla trådar.
single Låter dig ange att ett kodavsnitt ska köras på en enda tråd, inte nödvändigtvis huvudtråden.

För huvudtråd och synkronisering:

Directive Description
master Anger att endast huvudtråden ska köra ett avsnitt i programmet.
critical Anger att koden bara körs på en tråd i taget.
barrier Synkroniserar alla trådar i ett team. alla trådar pausar vid barriären tills alla trådar kör barriären.
atomic Anger att en minnesplats ska uppdateras atomiskt.
flush Anger att alla trådar har samma minnesvy för alla delade objekt.
ordered Anger att kod under en parallelliserad for loop ska köras som en sekventiell loop.

För datamiljö:

Directive Description
threadprivate Anger att en variabel är privat för en tråd.

atomic

Anger att en minnesplats som ska uppdateras atomiskt.

#pragma omp atomic
   expression

Parameters

expression
Instruktionen som har lvalue, vars minnesplats du vill skydda mot mer än en skrivning.

Remarks

Direktivet atomic stöder inga klausuler.

Mer information finns i 2.6.4 atomisk konstruktion.

Example

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

Synkroniserar alla trådar i ett team. alla trådar pausar vid barriären tills alla trådar kör barriären.

#pragma omp barrier

Remarks

Direktivet barrier stöder inga klausuler.

Mer information finns i 2.6.3 barriärdirektivet.

Example

Ett exempel på hur du använder barrierfinns i master.

critical

Anger att koden bara ska köras på en tråd i taget.

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

Parameters

name
(Valfritt) Ett namn som identifierar den kritiska koden. Namnet måste omges av parenteser.

Remarks

Direktivet critical stöder inga klausuler.

Mer information finns i 2.6.2 kritisk konstruktion.

Example

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

Anger att alla trådar har samma minnesvy för alla delade objekt.

#pragma omp flush [(var)]

Parameters

var
(Valfritt) En kommaavgränsad lista över variabler som representerar objekt som du vill synkronisera. Om var inte har angetts rensas allt minne.

Remarks

Direktivet flush stöder inga klausuler.

Mer information finns i 2.6.5 flush-direktivet.

Example

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

for

Gör att arbetet som utförs i en for loop i en parallell region delas upp mellan trådar.

#pragma omp [parallel] for [clauses]
   for_statement

Parameters

clauses
(Valfritt) Noll eller fler satser finns i avsnittet Kommentarer .

for_statement
En for loop. Odefinierat beteende resulterar i att användarkoden i loopen for ändrar indexvariabeln.

Remarks

Direktivet for stöder följande klausuler:

Om parallel anges också kan vara alla satser som godkänns av eller-direktiven parallelfor, förutom nowait. clauses

Mer information finns i 2.4.1 för konstruktion.

Example

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

Anger att endast huvudtråden ska köra ett avsnitt i programmet.

#pragma omp master
{
   code_block
}

Remarks

Direktivet master stöder inga klausuler.

Mer information finns i huvudkonstruktionen 2.6.1.

Om du vill ange att ett kodavsnitt ska köras på en enda tråd, inte nödvändigtvis huvudtråden, använder du det enskilda direktivet i stället.

Example

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

ordered

Anger att kod under en parallelliserad for loop ska köras som en sekventiell loop.

#pragma omp ordered
   structured-block

Remarks

Direktivet ordered måste ligga inom den dynamiska omfattningen av en för - eller parallel for konstruktion med en ordered klausul.

Direktivet ordered stöder inga klausuler.

Mer information finns i 2.6.6 ordnad konstruktion.

Example

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

Definierar en parallell region, som är kod som ska köras av flera trådar parallellt.

#pragma omp parallel [clauses]
{
   code_block
}

Parameters

clauses
(Valfritt) Noll eller fler satser finns i avsnittet Kommentarer .

Remarks

Direktivet parallel stöder följande klausuler:

parallel kan också användas med for - och avsnittsdirektiven .

Mer information finns i 2.3 parallell konstruktion.

Example

Följande exempel visar hur du anger antalet trådar och definierar en parallell region. Antalet trådar är som standard lika med antalet logiska processorer på datorn. Om du till exempel har en dator med en fysisk processor som har hypertråd aktiverat, har den två logiska processorer och två trådar. Ordningen på utdata kan variera på olika datorer.

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

Identifierar kodavsnitt som ska delas upp mellan alla trådar.

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

Parameters

clauses
(Valfritt) Noll eller fler satser finns i avsnittet Kommentarer .

Remarks

Direktivet sections kan innehålla noll eller fler section direktiv.

Direktivet sections stöder följande klausuler:

Om parallel anges också kan vara alla satser som godkänns av eller-direktiven parallelsections, förutom nowait. clauses

Mer information finns i 2.4.2-avsnittskonstruktionen.

Example

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

Låter dig ange att ett kodavsnitt ska köras på en enda tråd, inte nödvändigtvis huvudtråden.

#pragma omp single [clauses]
{
   code_block
}

Parameters

clauses
(Valfritt) Noll eller fler satser finns i avsnittet Kommentarer .

Remarks

Direktivet single stöder följande klausuler:

Mer information finns i 2.4.3 enkel konstruktion.

Om du vill ange att ett kodavsnitt bara ska köras på huvudtråden använder du huvuddirektivet i stället.

Example

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

Anger att en variabel är privat för en tråd.

#pragma omp threadprivate(var)

Parameters

var
En kommaavgränsad lista över variabler som du vill göra privata i en tråd. var måste vara antingen en global variabel eller en variabel med namnområdesomfång eller en lokal statisk variabel.

Remarks

Direktivet threadprivate stöder inga klausuler.

Direktivet threadprivate baseras på trådattributet med hjälp av nyckelordet __declspec. Begränsningar för __declspec(thread) gäller för .threadprivate En variabel finns till exempel threadprivate i alla trådar som startas i processen, inte bara de trådar som ingår i ett trådteam som skapas av en parallell region. Var medveten om den här implementeringsdetaljen. Du kanske märker att konstruktorer för en threadprivate användardefinierad typ anropas oftare än förväntat.

Du kan använda threadprivate i en DLL som är statiskt inläst vid processstart, men du kan inte använda threadprivate i någon DLL som läses in via LoadLibrary , till exempel DLL:er som läses in med /DELAYLOAD (import av fördröjningsbelastning), som också använder LoadLibrary.

En threadprivate variabel av en destruktbar typ garanteras inte att dess destruktor anropas. For example:

struct MyType
{
    ~MyType();
};

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

Användarna har ingen kontroll över när trådarna som utgör den parallella regionen avslutas. Om dessa trådar finns när processen avslutas meddelas inte trådarna om processavslutningen och destruktorn anropas inte för threaded_var någon tråd förutom den som avslutar (här den primära tråden). Kod bör därför inte räkna med korrekt förstörelse av threadprivate variabler.

Mer information finns i 2.7.1 threadprivate-direktivet.

Example

Ett exempel på hur du använder finns threadprivatei privat.