Clausole OpenMP
Fornisce collegamenti a clausole usate nell'API OpenMP.
Visual C++ supporta le clausole OpenMP seguenti.
Per gli attributi generali:
Clausola | Descrizione |
---|---|
if | Specifica se un ciclo deve essere eseguito in parallelo o in serie. |
num_threads | Imposta il numero di thread in un team di thread. |
ordinato | Obbligatorio in un'istruzione for parallela se deve essere usata una direttiva ordinata nel ciclo . |
schedule | Si applica alla direttiva for . |
nowait | Esegue l'override della barriera implicita in una direttiva . |
Per gli attributi di condivisione dei dati:
Clausola | Descrizione |
---|---|
private | Specifica che ogni thread deve avere una propria istanza di una variabile. |
firstprivate | Specifica che ogni thread deve avere una propria istanza di una variabile e che la variabile deve essere inizializzata con il valore della variabile, perché esiste prima del costrutto parallelo. |
lastprivate | Specifica che la versione del contesto di inclusione della variabile è impostata come uguale alla versione privata del thread che esegue l'iterazione finale (costrutto ciclo for) o all'ultima sezione (#pragma sezioni). |
condiviso | Specifica che una o più variabili devono essere condivise tra tutti i thread. |
default | Specifica il comportamento delle variabili senza ambito in un'area parallela. |
reduction | Specifica che una o più variabili private per ogni thread sono oggetto di un'operazione di riduzione alla fine dell'area parallela. |
copyin | Consente ai thread di accedere al valore del thread principale per una variabile threadprivate . |
copyprivate | Specifica che una o più variabili devono essere condivise tra tutti i thread. |
copyin
Consente ai thread di accedere al valore del thread principale per una variabile threadprivate .
copyin(var)
Parametri
var
Variabile threadprivate
che verrà inizializzata con il valore della variabile nel thread principale, come esiste prima del costrutto parallelo.
Osservazioni:
copyin
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.7 copyin.
Esempio
Vedere threadprivate per un esempio di uso copyin
di .
copyprivate
Specifica che una o più variabili devono essere condivise tra tutti i thread.
copyprivate(var)
Parametri
var
Una o più variabili da condividere. Se si specificano più variabili, separare i nomi delle variabili con una virgola.
Osservazioni:
copyprivate
si applica alla singola direttiva.
Per altre informazioni, vedere 2.7.2.8 copyprivate.
Esempio
// 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
impostazione predefinita
Specifica il comportamento delle variabili senza ambito in un'area parallela.
default(shared | none)
Osservazioni:
shared
, che è in vigore se la default
clausola non è specificata, significa che qualsiasi variabile in un'area parallela verrà considerata come se fosse specificata con la clausola condivisa . none
significa che qualsiasi variabile usata in un'area parallela che non ha come ambito la clausola private, condivisa, riduzione, firstprivate o lastprivate genererà un errore del compilatore.
default
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.5 default.For more information, see 2.7.2.5 default.
Esempio
Vedere private per un esempio di uso default
di .
firstprivate
Specifica che ogni thread deve avere una propria istanza di una variabile e che la variabile deve essere inizializzata con il valore della variabile, perché esiste prima del costrutto parallelo.
firstprivate(var)
Parametri
var
Variabile in cui sono presenti istanze in ogni thread e che verranno inizializzate con il valore della variabile, perché esiste prima del costrutto parallelo. Se si specificano più variabili, separare i nomi delle variabili con una virgola.
Osservazioni:
firstprivate
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.2 firstprivate.
Esempio
Per un esempio di uso firstprivate
di , vedere l'esempio in privato.
if (OpenMP)
Specifica se un ciclo deve essere eseguito in parallelo o in serie.
if(expression)
Parametri
expression
Espressione integrale che, se restituisce true (diverso da zero), fa sì che il codice nell'area parallela venga eseguito in parallelo. Se l'espressione restituisce false (zero), l'area parallela viene eseguita in serie (da un singolo thread).
Osservazioni:
if
si applica alle direttive seguenti:
Per altre informazioni, vedere Costrutto parallelo 2.3.
Esempio
// 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
Specifica che la versione del contesto di inclusione della variabile è impostata come uguale alla versione privata del thread che esegue l'iterazione finale (costrutto ciclo for) o all'ultima sezione (#pragma sezioni).
lastprivate(var)
Parametri
var
La variabile impostata come uguale alla versione privata del thread che esegue l'iterazione finale (costrutto ciclo for) o l'ultima sezione (#pragma sezioni).
Osservazioni:
lastprivate
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.3 lastprivate.
Esempio
Vedere pianificazione per un esempio di clausola using lastprivate
.
nowait
Esegue l'override della barriera implicita in una direttiva .
nowait
Osservazioni:
nowait
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.4.1 per costrutto, costrutto 2.4.2 sezioni e costrutto singolo 2.4.3.
Esempio
// 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
Imposta il numero di thread in un team di thread.
num_threads(num)
Parametri
num
Numero di thread
Osservazioni:
La num_threads
clausola ha la stessa funzionalità della funzione omp_set_num_threads .
num_threads
si applica alle direttive seguenti:
Per altre informazioni, vedere Costrutto parallelo 2.3.
Esempio
Vedere parallel per un esempio di clausola using num_threads
.
ordered
Obbligatorio in un'istruzione for parallela se deve essere usata una direttiva ordinata nel ciclo .
ordered
Osservazioni:
ordered
si applica alla direttiva for .
Per altre informazioni, vedere 2.4.1 per costrutto.
Esempio
Vedere ordinato per un esempio di clausola using ordered
.
private
Specifica che ogni thread deve avere una propria istanza di una variabile.
private(var)
Parametri
var
Variabile in cui includere istanze in ogni thread.
Osservazioni:
private
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.1 private.
Esempio
// 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)
riduzione
Specifica che una o più variabili private per ogni thread sono oggetto di un'operazione di riduzione alla fine dell'area parallela.
reduction(operation:var)
Parametri
operation
Operatore per l'operazione da eseguire sulle variabili var alla fine dell'area parallela.
var
Una o più variabili su cui eseguire la riduzione scalare. Se si specificano più variabili, separare i nomi delle variabili con una virgola.
Osservazioni:
reduction
si applica alle direttive seguenti:
Per altre informazioni, vedere Riduzione 2.7.2.6.
Esempio
// 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!
programmazione
Si applica alla direttiva for .
schedule(type[,size])
Parametri
type
Tipo di pianificazione, , dynamic
guided
, runtime
o static
.
size
(Facoltativo) Specifica le dimensioni delle iterazioni. le dimensioni devono essere un numero intero. Non valido quando il tipo è runtime
.
Osservazioni:
Per altre informazioni, vedere 2.4.1 per costrutto.
Esempio
// 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 |
------------------------------------------------
Condiviso
Specifica che una o più variabili devono essere condivise tra tutti i thread.
shared(var)
Parametri
var
Una o più variabili da condividere. Se si specificano più variabili, separare i nomi delle variabili con una virgola.
Osservazioni:
Un altro modo per condividere le variabili tra i thread consiste nella clausola copyprivate .
shared
si applica alle direttive seguenti:
Per altre informazioni, vedere 2.7.2.4 condiviso.
Esempio
Vedere private per un esempio di uso shared
di .