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
ordered
s’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
, runtime
ou 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
.