Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Fornisce collegamenti alle direttive usate nell'API OpenMP.
Visual C++ supporta le direttive OpenMP seguenti.
Per la condivisione di lavoro parallela:
| Directive | Description |
|---|---|
| parallel | Definisce un'area parallela, ovvero codice che verrà eseguito da più thread in parallelo. |
| for | Fa in modo che il lavoro eseguito in un for ciclo all'interno di un'area parallela venga diviso tra i thread. |
| sections | Identifica le sezioni di codice da dividere tra tutti i thread. |
| single | Consente di specificare che una sezione di codice deve essere eseguita su un singolo thread, non necessariamente il thread principale. |
Per il thread principale e la sincronizzazione:
| Directive | Description |
|---|---|
| master | Specifica che solo il thread principale deve eseguire una sezione del programma. |
| critical | Specifica che il codice viene eseguito solo su un thread alla volta. |
| barrier | Sincronizza tutti i thread in un team; tutti i thread si sospendono sulla barriera, fino a quando tutti i thread non eseguono la barriera. |
| atomic | Specifica che una posizione di memoria verrà aggiornata in modo atomico. |
| flush | Specifica che tutti i thread hanno la stessa visualizzazione della memoria per tutti gli oggetti condivisi. |
| ordered | Specifica che il codice in un ciclo parallelizzato for deve essere eseguito come un ciclo sequenziale. |
Per l'ambiente dati:
| Directive | Description |
|---|---|
| threadprivate | Specifica che una variabile è privata per un thread. |
atomic
Specifica che una posizione di memoria che verrà aggiornata in modo atomico.
#pragma omp atomic
expression
Parameters
expression
Istruzione con lvalue, la cui posizione di memoria si vuole proteggere da più di una scrittura.
Remarks
La atomic direttiva non supporta clausole.
Per altre informazioni, vedere Costrutto atomico 2.6.4.
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
Sincronizza tutti i thread in un team; tutti i thread si sospendono sulla barriera, fino a quando tutti i thread non eseguono la barriera.
#pragma omp barrier
Remarks
La barrier direttiva non supporta clausole.
Per altre informazioni, vedere direttiva barriera 2.6.3.
Example
Per un esempio di come usare barrier, vedere master.
critical
Specifica che il codice viene eseguito solo su un thread alla volta.
#pragma omp critical [(name)]
{
code_block
}
Parameters
name
(Facoltativo) Nome per identificare il codice critico. Il nome deve essere racchiuso tra parentesi.
Remarks
La critical direttiva non supporta clausole.
Per altre informazioni, vedere Costrutto critico 2.6.2.
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
Specifica che tutti i thread hanno la stessa visualizzazione della memoria per tutti gli oggetti condivisi.
#pragma omp flush [(var)]
Parameters
var
(Facoltativo) Elenco delimitato da virgole di variabili che rappresentano gli oggetti da sincronizzare. Se var non è specificato, tutta la memoria viene scaricata.
Remarks
La flush direttiva non supporta clausole.
Per altre informazioni, vedere direttiva flush 2.6.5.
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
Fa in modo che il lavoro eseguito in un for ciclo all'interno di un'area parallela venga diviso tra i thread.
#pragma omp [parallel] for [clauses]
for_statement
Parameters
clauses
(Facoltativo) Zero o più clausole, vedere la sezione Osservazioni .
for_statement
Ciclo .for Il comportamento non definito genererà se il codice utente nel for ciclo modifica la variabile di indice.
Remarks
La for direttiva supporta le clausole seguenti:
Se parallel viene specificato anche , clauses può essere qualsiasi clausola accettata dalle parallel direttive o for , ad eccezione di nowait.
Per altre informazioni, vedere 2.4.1 per costrutto.
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
Specifica che solo il thread principale deve eseguire una sezione del programma.
#pragma omp master
{
code_block
}
Remarks
La master direttiva non supporta clausole.
Per altre informazioni, vedere 2.6.1 costrutto master.
Per specificare che una sezione di codice deve essere eseguita in un singolo thread, non necessariamente nel thread principale, usare invece la singola direttiva.
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
Specifica che il codice in un ciclo parallelizzato for deve essere eseguito come un ciclo sequenziale.
#pragma omp ordered
structured-block
Remarks
La ordered direttiva deve trovarsi all'interno dell'extent dinamico di un oggetto perparallel forcostrutto con una ordered clausola .
La ordered direttiva non supporta clausole.
Per altre informazioni, vedere Costrutto ordinato 2.6.6.
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
Definisce un'area parallela, ovvero codice che verrà eseguito da più thread in parallelo.
#pragma omp parallel [clauses]
{
code_block
}
Parameters
clauses
(Facoltativo) Zero o più clausole, vedere la sezione Osservazioni .
Remarks
La parallel direttiva supporta le clausole seguenti:
parallel può essere usato anche con le direttive for e sections .
Per altre informazioni, vedere Costrutto parallelo 2.3.
Example
L'esempio seguente illustra come impostare il numero di thread e definire un'area parallela. Il numero di thread è uguale per impostazione predefinita al numero di processori logici nel computer. Ad esempio, se si dispone di un computer con un processore fisico con hyperthreading abilitato, avrà due processori logici e due thread. L'ordine di output può variare in computer diversi.
// 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
Identifica le sezioni di codice da dividere tra tutti i thread.
#pragma omp [parallel] sections [clauses]
{
#pragma omp section
{
code_block
}
}
Parameters
clauses
(Facoltativo) Zero o più clausole, vedere la sezione Osservazioni .
Remarks
La sections direttiva può contenere zero o più section direttive.
La sections direttiva supporta le clausole seguenti:
Se parallel viene specificato anche , clauses può essere qualsiasi clausola accettata dalle parallel direttive o sections , ad eccezione di nowait.
Per altre informazioni, vedere costrutto delle sezioni 2.4.2.
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
Consente di specificare che una sezione di codice deve essere eseguita su un singolo thread, non necessariamente il thread principale.
#pragma omp single [clauses]
{
code_block
}
Parameters
clauses
(Facoltativo) Zero o più clausole, vedere la sezione Osservazioni .
Remarks
La single direttiva supporta le clausole seguenti:
Per altre informazioni, vedere 2.4.3 costrutto singolo.
Per specificare che una sezione di codice deve essere eseguita solo nel thread principale, usare invece la direttiva master .
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
Specifica che una variabile è privata per un thread.
#pragma omp threadprivate(var)
Parameters
var
Elenco delimitato da virgole di variabili che si desidera rendere private in un thread.
var deve essere una variabile globale o con ambito spazio dei nomi o una variabile statica locale.
Remarks
La threadprivate direttiva non supporta clausole.
La threadprivate direttiva si basa sull'attributo del thread usando la parola chiave __declspec ; i limiti applicati a __declspec(thread) si applicano a threadprivate. Ad esempio, una threadprivate variabile esisterà in qualsiasi thread avviato nel processo, non solo in quelli che fanno parte di un team di thread generato da un'area parallela. Tenere presente questo dettaglio di implementazione; è possibile notare che i costruttori per un threadprivate tipo definito dall'utente vengono chiamati più spesso previsti.
È possibile usare threadprivate in una DLL caricata in modo statico all'avvio del processo, ma non è possibile usare threadprivate in alcuna DLL che verrà caricata tramite LoadLibrary , ad esempio dll caricate con /DELAYLOAD (importazione di caricamento ritardato) che usa LoadLibraryanche .
Non threadprivate è garantito che una variabile di un tipo distruttore abbia chiamato il distruttore. For example:
struct MyType
{
~MyType();
};
MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
#pragma omp parallel
{}
}
Gli utenti non hanno alcun controllo su quando i thread che costituiscono l'area parallela termineranno. Se questi thread sono presenti quando il processo viene chiuso, i thread non riceveranno una notifica sull'uscita del processo e il distruttore non verrà chiamato per threaded_var in alcun thread, ad eccezione di quello che esce (in questo caso, il thread primario). Pertanto, il codice non deve contare sulla corretta distruzione delle threadprivate variabili.
Per altre informazioni, vedere direttiva threadprivate 2.7.1.
Example
Per un esempio di uso threadprivatedi , vedere private.