Partager via


Clauses OpenMP

Fournit des liens vers des clauses utilisées dans l’API OpenMP.

Visual C++ prend en charge les clauses OpenMP suivantes.

Pour les attributs généraux :

Clause Description
if Spécifie si une boucle doit être exécutée en parallèle ou en série.
num_threads Définit le nombre de threads dans une équipe de threads.
ordonné Obligatoire sur une instruction parallèle si une directive ordonnée doit être utilisée dans la boucle.
schedule S’applique à la directive.
nowait Remplace la barrière implicite dans une directive.

Pour les attributs de partage de données :

Clause Description
private Spécifie que chaque thread doit avoir sa propre instance d’une variable.
firstprivate Spécifie que chaque thread doit avoir sa propre instance d’une variable et que la variable doit être initialisée avec la valeur de la variable, car elle existe avant la construction parallèle.
lastprivate Spécifie que la version du contexte englobant de la variable est définie sur la version privée de laquelle le thread exécute l’itération finale (construction de boucle for) ou la dernière section (sections #pragma).
partagé Spécifie qu’une ou plusieurs variables doivent être partagées entre tous les threads.
default Spécifie le comportement des variables non portées dans une région parallèle.
reduction Spécifie qu’une ou plusieurs variables privées à chaque thread font l’objet d’une opération de réduction à la fin de la région parallèle.
copyin Permet aux threads d’accéder à la valeur du thread principal, pour une variable threadprivate .
copyprivate Spécifie qu’une ou plusieurs variables doivent être partagées entre tous les threads.

copyin

Permet aux threads d’accéder à la valeur du thread principal, pour une variable threadprivate .

copyin(var)

Paramètres

var
Variable threadprivate qui sera initialisée avec la valeur de la variable dans le thread principal, telle qu’elle existe avant la construction parallèle.

Notes

copyin s’applique aux directives suivantes :

Pour plus d’informations, consultez la copie 2.7.2.7.

Exemple

Consultez threadprivate pour obtenir un exemple d’utilisation copyin.

copyprivate

Spécifie qu’une ou plusieurs variables doivent être partagées entre tous les threads.

copyprivate(var)

Paramètres

var
Une ou plusieurs variables à partager. Si plusieurs variables sont spécifiées, séparez les noms de variables avec une virgule.

Notes

copyprivate s’applique à la directive unique .

Pour plus d’informations, consultez la version 2.7.2.8 copyprivate.

Exemple

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

Spécifie le comportement des variables non portées dans une région parallèle.

default(shared | none)

Notes

shared, qui est en vigueur si la default clause n’est pas spécifiée, signifie que toute variable d’une région parallèle sera traitée comme si elle a été spécifiée avec la clause partagée . none signifie que toutes les variables utilisées dans une région parallèle qui ne sont pas étendues avec la clause privée, partagée, réduction, firstprivate ou lastprivate entraînent une erreur du compilateur.

default s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.7.2.5 par défaut.

Exemple

Voir privé pour obtenir un exemple d’utilisation default.

firstprivate

Spécifie que chaque thread doit avoir sa propre instance d’une variable et que la variable doit être initialisée avec la valeur de la variable, car elle existe avant la construction parallèle.

firstprivate(var)

Paramètres

var
Variable à avoir des instances dans chaque thread et qui seront initialisées avec la valeur de la variable, car elle existe avant la construction parallèle. Si plusieurs variables sont spécifiées, séparez les noms de variables avec une virgule.

Notes

firstprivate s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.7.2.2 firstprivate.

Exemple

Pour obtenir un exemple d’utilisation firstprivate, consultez l’exemple en privé.

if (OpenMP)

Spécifie si une boucle doit être exécutée en parallèle ou en série.

if(expression)

Paramètres

expression
Expression intégrale qui, si elle prend la valeur true (différent de zéro), provoque l’exécution du code dans la région parallèle. Si l’expression a la valeur false (zéro), la région parallèle est exécutée en série (par un thread unique).

Notes

if s’applique aux directives suivantes :

Pour plus d’informations, consultez la construction parallèle 2.3.

Exemple

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

Spécifie que la version du contexte englobant de la variable est définie sur la version privée de laquelle le thread exécute l’itération finale (construction de boucle for) ou la dernière section (sections #pragma).

lastprivate(var)

Paramètres

var
Variable définie égale à la version privée du thread qui exécute l’itération finale (construction de boucle for) ou dernière section (sections #pragma).

Notes

lastprivate s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.7.2.3 lastprivate.

Exemple

Consultez la planification pour obtenir un exemple de clause Using lastprivate .

nowait

Remplace la barrière implicite dans une directive.

nowait

Notes

nowait s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.4.1 pour la construction, la construction de sections 2.4.2 et la construction unique 2.4.3.

Exemple

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

Définit le nombre de threads dans une équipe de threads.

num_threads(num)

Paramètres

num
Nombre de threads

Notes

La num_threads clause a la même fonctionnalité que la fonction omp_set_num_threads .

num_threads s’applique aux directives suivantes :

Pour plus d’informations, consultez la construction parallèle 2.3.

Exemple

Consultez le parallèle pour obtenir un exemple de clause using num_threads .

ordered

Obligatoire sur une instruction parallèle si une directive ordonnée doit être utilisée dans la boucle.

ordered

Notes

ordereds’applique à la directive.

Pour plus d’informations, consultez la version 2.4.1 pour la construction.

Exemple

Consultez trié pour obtenir un exemple de clause using ordered .

private

Spécifie que chaque thread doit avoir sa propre instance d’une variable.

private(var)

Paramètres

var
Variable à avoir des instances dans chaque thread.

Notes

private s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.7.2.1 privée.

Exemple

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

Spécifie qu’une ou plusieurs variables privées à chaque thread font l’objet d’une opération de réduction à la fin de la région parallèle.

reduction(operation:var)

Paramètres

de commutation
Opérateur de l’opération à effectuer sur les variables var à la fin de la région parallèle.

var
Une ou plusieurs variables sur lesquelles effectuer une réduction scalaire. Si plusieurs variables sont spécifiées, séparez les noms de variables avec une virgule.

Notes

reduction s’applique aux directives suivantes :

Pour plus d’informations, consultez la réduction 2.7.2.6.

Exemple

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

S’applique à la directive.

schedule(type[,size])

Paramètres

type
Type de planification, soit dynamic, , guided, runtimeou static.

size
(Facultatif) Spécifie la taille des itérations. la taille doit être un entier. Non valide lorsque le type est runtime.

Notes

Pour plus d’informations, consultez la version 2.4.1 pour la construction.

Exemple

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

partagé

Spécifie qu’une ou plusieurs variables doivent être partagées entre tous les threads.

shared(var)

Paramètres

var
Une ou plusieurs variables à partager. Si plusieurs variables sont spécifiées, séparez les noms de variables avec une virgule.

Notes

Une autre façon de partager des variables entre des threads est avec la clause copyprivate .

shared s’applique aux directives suivantes :

Pour plus d’informations, consultez la version 2.7.2.4 partagée.

Exemple

Voir privé pour obtenir un exemple d’utilisation shared.