Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Stellt Links zu Direktiven bereit, die in der OpenMP-API verwendet werden.
Visual C++ unterstützt die folgenden OpenMP-Direktiven.
Für parallele Arbeitsfreigabe:
| Directive | Description |
|---|---|
| parallel | Definiert einen parallelen Bereich, der Code ist, der von mehreren Threads parallel ausgeführt wird. |
| for | Bewirkt, dass die Arbeit in einer for Schleife innerhalb eines parallelen Bereichs in Threads aufgeteilt wird. |
| sections | Identifiziert Codeabschnitte, die in alle Threads unterteilt werden sollen. |
| single | Hiermit können Sie angeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, nicht unbedingt der Hauptthread. |
Für Hauptthread und Synchronisierung:
| Directive | Description |
|---|---|
| master | Gibt an, dass nur der Hauptthread einen Abschnitt des Programms ausführen soll. |
| critical | Gibt an, dass Code nur jeweils auf einem Thread ausgeführt wird. |
| barrier | Synchronisiert alle Threads in einem Team; Alle Threads halten an der Barriere an, bis alle Threads die Barriere ausführen. |
| atomic | Gibt an, dass ein Speicherspeicherort atomisch aktualisiert wird. |
| flush | Gibt an, dass alle Threads dieselbe Ansicht des Arbeitsspeichers für alle freigegebenen Objekte aufweisen. |
| ordered | Gibt an, dass Code unter einer parallelisierten for Schleife wie eine sequenzielle Schleife ausgeführt werden soll. |
Für Datenumgebung:
| Directive | Description |
|---|---|
| threadprivate | Gibt an, dass eine Variable für einen Thread privat ist. |
atomic
Gibt an, dass ein Speicherspeicherort, der atomisch aktualisiert wird.
#pragma omp atomic
expression
Parameters
expression
Die Anweisung mit dem Wert "lvalue", deren Speicherspeicherort Sie vor mehreren Schreibvorgängen schützen möchten.
Remarks
Die atomic Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie unter 2.6.4 Atomkonstrukt.
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
Synchronisiert alle Threads in einem Team; Alle Threads halten an der Barriere an, bis alle Threads die Barriere ausführen.
#pragma omp barrier
Remarks
Die barrier Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie in der Barriererichtlinie 2.6.3.
Example
Ein Beispiel für die Verwendung barrierfinden Sie unter Master.
critical
Gibt an, dass Code nur auf einem Thread gleichzeitig ausgeführt wird.
#pragma omp critical [(name)]
{
code_block
}
Parameters
name
(Optional) Ein Name zum Identifizieren des kritischen Codes. Der Name muss in Klammern eingeschlossen werden.
Remarks
Die critical Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie im kritischen Konstrukt 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
Gibt an, dass alle Threads dieselbe Ansicht des Arbeitsspeichers für alle freigegebenen Objekte aufweisen.
#pragma omp flush [(var)]
Parameters
var
(Optional) Eine durch Trennzeichen getrennte Liste von Variablen, die Objekte darstellen, die Sie synchronisieren möchten. Wenn "var " nicht angegeben ist, wird der gesamte Arbeitsspeicher geleert.
Remarks
Die flush Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie unter 2.6.5 Flush-Direktive.
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
Bewirkt, dass die Arbeit in einer for Schleife innerhalb eines parallelen Bereichs in Threads aufgeteilt wird.
#pragma omp [parallel] for [clauses]
for_statement
Parameters
clauses
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".
for_statement
Eine for Schleife. Das nicht definierte Verhalten führt dazu, dass der Benutzercode in der for Schleife die Indexvariable ändert.
Remarks
Die for Direktive unterstützt die folgenden Klauseln:
Wenn parallel auch angegeben, kann eine beliebige Klausel sein, clauses die von den parallel Richtlinien for akzeptiert wird, außer nowait.
Weitere Informationen finden Sie unter 2.4.1 für das Konstrukt.
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
Gibt an, dass nur der Hauptthread einen Abschnitt des Programms ausführen soll.
#pragma omp master
{
code_block
}
Remarks
Die master Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie unter 2.6.1 Master-Konstrukt.
Um anzugeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, verwenden Sie stattdessen die einzelne Direktive, nicht unbedingt den Hauptthread.
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
Gibt an, dass Code unter einer parallelisierten for Schleife wie eine sequenzielle Schleife ausgeführt werden soll.
#pragma omp ordered
structured-block
Remarks
Die ordered Richtlinie muss sich innerhalb des dynamischen Umfangs eines For- oder parallel for Konstruierens mit einer ordered Klausel belassen.
Die ordered Direktive unterstützt keine Klauseln.
Weitere Informationen finden Sie unter 2.6.6 geordnetes Konstrukt.
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
Definiert einen parallelen Bereich, der Code ist, der von mehreren Threads parallel ausgeführt wird.
#pragma omp parallel [clauses]
{
code_block
}
Parameters
clauses
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".
Remarks
Die parallel Direktive unterstützt die folgenden Klauseln:
parallel kann auch mit den Für - und Abschnittsdirektiven verwendet werden.
Weitere Informationen finden Sie unter 2.3 paralleles Konstrukt.
Example
Das folgende Beispiel zeigt, wie Sie die Anzahl der Threads festlegen und einen parallelen Bereich definieren. Die Anzahl der Threads entspricht standardmäßig der Anzahl der logischen Prozessoren auf dem Computer. Wenn Sie z. B. einen Computer mit einem physischen Prozessor haben, der Hyperthreading aktiviert hat, verfügen sie über zwei logische Prozessoren und zwei Threads. Die Ausgabereihenfolge kann auf verschiedenen Computern variieren.
// 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
Identifiziert Codeabschnitte, die in alle Threads unterteilt werden sollen.
#pragma omp [parallel] sections [clauses]
{
#pragma omp section
{
code_block
}
}
Parameters
clauses
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".
Remarks
Die sections Direktive kann null oder mehr section Direktiven enthalten.
Die sections Direktive unterstützt die folgenden Klauseln:
Wenn parallel auch angegeben, kann eine beliebige Klausel sein, clauses die von den parallel Richtlinien sections akzeptiert wird, außer nowait.
Weitere Informationen finden Sie im Abschnittskonstrukt 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
Hiermit können Sie angeben, dass ein Codeabschnitt in einem einzelnen Thread ausgeführt werden soll, nicht unbedingt der Hauptthread.
#pragma omp single [clauses]
{
code_block
}
Parameters
clauses
(Optional) Null oder mehr Klauseln finden Sie im Abschnitt "Hinweise ".
Remarks
Die single Direktive unterstützt die folgenden Klauseln:
Weitere Informationen finden Sie unter 2.4.3 single construct.
Um anzugeben, dass ein Codeabschnitt nur im Hauptthread ausgeführt werden soll, verwenden Sie stattdessen die Masterdirektive .
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
Gibt an, dass eine Variable für einen Thread privat ist.
#pragma omp threadprivate(var)
Parameters
var
Eine durch Trennzeichen getrennte Liste von Variablen, die Sie als privat für einen Thread festlegen möchten.
var muss entweder eine globale oder namespacebezogene Variable oder eine lokale statische Variable sein.
Remarks
Die threadprivate Direktive unterstützt keine Klauseln.
Die threadprivate Direktive basiert auf dem Thread-Attribut mit dem schlüsselwort __declspec ; limits on __declspec(thread) apply to threadprivate. Beispielsweise ist eine threadprivate Variable in jedem Thread vorhanden, der im Prozess gestartet wurde, nicht nur in den Threads, die Teil eines Threadteams sind, der von einem parallelen Bereich bereitgestellt wird. Seien Sie sich dieser Implementierungsdetails bewusst; Möglicherweise stellen Sie fest, dass Konstruktoren für einen threadprivate benutzerdefinierten Typ häufiger als erwartet bezeichnet werden.
Sie können in einer DLL verwenden threadprivate , die beim Prozessstart statisch geladen wird. Sie können jedoch keine DLL verwenden threadprivate , die über LoadLibrary geladen wird, z. B. DLLs, die mit /DELAYLOAD (Verzögerungsladeimport) geladen werden, die ebenfalls verwendet LoadLibrarywerden.
Eine threadprivate Variable eines destruktierbaren Typs ist nicht garantiert, dass der Destruktor aufgerufen wird. For example:
struct MyType
{
~MyType();
};
MyType threaded_var;
#pragma omp threadprivate(threaded_var)
int main()
{
#pragma omp parallel
{}
}
Benutzer haben keine Kontrolle darüber, wann die Threads, die den parallelen Bereich bilden, beendet werden. Wenn diese Threads vorhanden sind, wenn der Prozess beendet wird, werden die Threads nicht über den Prozessende benachrichtigt, und der Destruktor wird für keinen Thread aufgerufen threaded_var , außer für den Thread, der beendet wird (hier der primäre Thread). Daher sollte code nicht auf die ordnungsgemäße Zerstörung von threadprivate Variablen zählen.
Weitere Informationen finden Sie unter der Threadprivate-Direktive 2.7.1.
Example
Ein Beispiel für die Verwendung threadprivatefinden Sie unter "Privat".