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.
Visual C++ unterstützt derzeit den OpenMP 2.0-Standard, visual Studio 2019 bietet jedoch jetzt auch SIMD-Funktionen.
Hinweis
Um SIMD zu verwenden, kompilieren Sie mit dem -openmp:experimental Switch, der zusätzliche OpenMP-Features ermöglicht, die bei Verwendung des -openmp Schalters nicht verfügbar sind.
Der -openmp:experimental Schalter subsumiert -openmp, was bedeutet, dass alle OpenMP 2.0-Funktionen enthalten sind.
Weitere Informationen finden Sie unter SIMD-Erweiterung zu C++ OpenMP in Visual Studio.
OpenMP SIMD in Visual C++
OpenMP SIMD, eingeführt im OpenMP 4.0-Standard, zielt darauf ab, vektorfreundliche Schleifen zu ermöglichen. Durch die Verwendung der simd Direktive vor einer Schleife kann der Compiler Vektorabhängigkeiten ignorieren, die Schleife so vektorfreundlich wie möglich gestalten und die Absicht der Anwender respektieren, mehrere Schleifeniterationen gleichzeitig auszuführen.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
Visual C++ bietet ähnliche Nicht-OpenMP-Schleifen pragmas wie #pragma vector und #pragma ivdep, jedoch mit OpenMP SIMD, kann der Compiler mehr tun, z. B.:
- Es ist immer zulässig, vorhandene Vektorabhängigkeiten zu ignorieren.
-
/fp:fastist innerhalb der Schleife aktiviert. - Äußere Schleifen und Schleifen mit Funktionsaufrufen sind vektorfreundlich.
- Geschachtelte Schleifen können in einer Schleife zusammengeführt und vektorfreundlich gestaltet werden.
- Hybride Beschleunigung mit
#pragma omp for simd, um grobkörniges Multithreading und feinkörnige Vektoren zu ermöglichen.
Bei vektorfreundlichen Schleifen schweigt der Compiler, es sei denn, Sie verwenden eine Vektorunterstützungsprotokollierungsoption:
cl -O2 -openmp:experimental -Qvec-report:2 mycode.cpp
mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(96) : info C5001: Omp simd loop vectorized
Bei nicht vektorfreundlichen Schleifen gibt der Compiler für jede eine Nachricht aus:
cl -O2 -openmp:experimental mycode.cpp
mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'
Klauseln
Die OpenMP SIMD-Direktive kann auch die folgenden Klauseln verwenden, um die Vektorunterstützung zu verbessern:
| Richtlinie | Beschreibung |
|---|---|
simdlen(length) |
Geben Sie die Anzahl der Vektorspuren an. |
safelen(length) |
Geben Sie den Vektorabhängigkeitsabstand an. |
linear(list[ : linear-step]) |
Die lineare Zuordnung von Schleifeninduktionsvariablen zum Arrayabonnement. |
aligned(list[ : alignment]) |
Die Ausrichtung der Daten. |
private(list) |
Geben Sie die Datenpriorisierung an. |
lastprivate(list) |
Geben Sie die Datenprivatisierung mit endgültigem Wert aus der letzten Iteration an. |
reduction(reduction-identifier:list) |
Geben Sie angepasste Reduzierungsvorgänge an. |
collapse(n) |
Verschachtelung der Schleife. |
Hinweis
Nicht effektive SIMD-Klauseln werden vom Compiler mit einer Warnung analysiert und ignoriert.
Die Verwendung des folgenden Codes gibt beispielsweise eine Warnung aus:
#pragma omp simd simdlen(8)
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
warning C4849: OpenMP 'simdlen' clause ignored in 'simd' directive
Beispiel
Die OpenMP SIMD-Direktive bietet Benutzern eine Möglichkeit, den Compiler zu diktieren, um Schleifen vektorfreundlich zu gestalten. Durch das Annotieren einer Schleife mit der OpenMP SIMD-Direktive beabsichtigen Benutzer, mehrere Schleifeniterationen gleichzeitig ausgeführt werden zu lassen.
Die folgende Schleife ist beispielsweise mit der OpenMP SIMD-Anweisung annotiert. Es gibt keine perfekte Parallelität zwischen Schleifeniterationen, da es eine Rückwärtsabhängigkeit von a[i] zu a[i-1] gibt, aber aufgrund der SIMD-Direktive darf der Compiler immer noch aufeinander folgende Iterationen der ersten Anweisung in eine Vektoranweisung packen und parallel ausführen.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
Daher ist die folgende transformierte Vektorform der Schleife legal , da der Compiler das sequenzielle Verhalten jeder ursprünglichen Schleifeniteration behält. Mit anderen Worten, a[i] wird nach a[-1] ausgeführt, b[i] erfolgt nach a[i], und der Aufruf von bar passiert zuletzt.
for (i = 0; i < count; i+=4)
{
a[i:i+3] = a[i-1:i+2] + 1;
b[i:i+3] = *c + 1;
bar(i);
bar(i+1);
bar(i+2);
bar(i+3);
}
Es ist nicht zulässig, den Speicherverweis *c aus der Schleife zu verschieben, wenn er sich mit a[i] oder b[i] überschneiden könnte. Es ist auch nicht zulässig, die Anweisungen innerhalb einer ursprünglichen Iteration neu anzuordnen, wenn die sequenzielle Abhängigkeit unterbrochen wird. Die folgende transformierte Schleife ist beispielsweise nicht zulässig:
c = b;
t = *c;
for (i = 0; i < count; i+=4)
{
a[i:i+3] = a[i-1:i+2] + 1;
bar(i); // illegal to reorder if bar[i] depends on b[i]
b[i:i+3] = t + 1; // illegal to move *c out of the loop
bar(i+1);
bar(i+2);
bar(i+3);
}