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.
Die -openmp:experimental
Switch-Untersummen -openmp
, was bedeutet, dass alle OpenMP 2.0-Features in der Verwendung 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 machen. Durch die Verwendung der simd
Direktive vor einer Schleife kann der Compiler Vektorabhängigkeiten ignorieren, die Vektoren so vektorfreundlich wie möglich gestalten und die Absicht der Benutzer 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:fast
ist 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.
- Hybridbeschleunigung,
#pragma omp for simd
um grobkörnige Multithreading- und feinkörnige Vektoren zu ermöglichen.
Bei vektorfreundlichen Schleifen bleibt der Compiler unbeaufsichtigt, es sei denn, Sie verwenden einen Vektorunterstützungsprotokollschalter:
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 jede 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:
Anweisung | 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 Datenpriorisierung 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 Kommentieren einer Schleife mit der OpenMP SIMD-Direktive beabsichtigen Benutzer, mehrere Schleifeniterationen gleichzeitig auszuführen.
Die folgende Schleife wird beispielsweise mit der OpenMP SIMD-Direktive kommentiert. 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]
ist nach b[i]
a[i]
und der Aufrufbar
, der zuletzt erfolgt.
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 alias mit a[i]
oder b[i]
. 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);
}