Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Program Visual C++ obecnie obsługuje standard OpenMP 2.0, jednak program Visual Studio 2019 oferuje teraz również funkcje SIMD.
Uwaga
Aby użyć simD, skompiluj -openmp:experimental
z przełącznikiem, który umożliwia dodatkowe funkcje OpenMP niedostępne podczas korzystania z przełącznika -openmp
.
Podsumowy -openmp:experimental
przełącznika -openmp
, co oznacza, że wszystkie funkcje protokołu OpenMP 2.0 są uwzględniane w jego użyciu.
Aby uzyskać więcej informacji, zobacz Rozszerzenie SIMD do C++ OpenMP w programie Visual Studio.
OpenMP SIMD w Visual C++
OpenMP SIMD, wprowadzony w standardzie OpenMP 4.0, cele sprawiają, że pętle przyjazne dla wektorów. Korzystając z simd
dyrektywy przed pętlą, kompilator może ignorować zależności wektorowe, uczynić pętlę tak przyjazną dla wektorów, jak to możliwe i przestrzegać intencji użytkowników, aby wykonać jednocześnie wiele iteracji pętli.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
Język Visual C++ udostępnia podobne pragmay pętli inne niż OpenMP, takie jak #pragma vector
i #pragma ivdep
, jednak w przypadku protokołu OPENMP SIMD kompilator może wykonywać więcej czynności, takich jak:
- Zawsze zezwalaj na ignorowanie obecnych zależności wektorów.
-
/fp:fast
jest włączona w pętli. - Pętle zewnętrzne i pętle z wywołaniami funkcji są przyjazne dla wektorów.
- Zagnieżdżone pętle można połączyć w jedną pętlę i być przyjazne dla wektorów.
- Przyspieszanie hybrydowe z
#pragma omp for simd
systemem w celu umożliwienia gruboziarnistych wielowątków i precyzyjnych wektorów.
W przypadku pętli przyjaznych dla wektorów kompilator pozostaje cichy, chyba że używasz przełącznika dziennika obsługującego wektory:
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
W przypadku pętli przyjaznych dla wektorów kompilator wystawia każdy komunikat:
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'
Klauzule
Dyrektywa OPENMP SIMD może również przyjąć następujące klauzule, aby zwiększyć obsługę wektorów:
Dyrektywa | opis |
---|---|
simdlen(length) |
Określ liczbę pasów wektorowych. |
safelen(length) |
Określ odległość zależności wektora. |
linear(list[ : linear-step] ) |
Mapowanie liniowe ze zmiennej indukcyjnej pętli do subskrypcji tablicy. |
aligned(list[ : alignment]) |
Wyrównanie danych. |
private(list) |
Określ prywatyzację danych. |
lastprivate(list) |
Określ prywatyzację danych z ostateczną wartością z ostatniej iteracji. |
reduction(reduction-identifier:list) |
Określ dostosowane operacje redukcji. |
collapse(n) |
Zagnieżdżanie pętli łączenia. |
Uwaga
Niedozwolone klauzule SIMD są analizowane i ignorowane przez kompilator z ostrzeżeniem.
Na przykład użycie następującego kodu generuje ostrzeżenie:
#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
Przykład
Dyrektywa SIMD openMP zapewnia użytkownikom sposób dyktowania pętli kompilatora wektorów przyjaznych dla wektorów. Dodając adnotację do pętli z dyrektywą OpenMP SIMD, użytkownicy zamierzają wykonać jednocześnie wiele iteracji pętli.
Na przykład następująca pętla jest oznaczona adnotacją dyrektywy OpenMP SIMD. Nie ma doskonałego równoległości między iteracjami pętli, ponieważ istnieje zależność wsteczna od [i] do [i-1], ale ze względu na dyrektywę SIMD kompilator nadal może pakować kolejne iteracji pierwszej instrukcji do jednej instrukcji wektorowej i uruchamiać je równolegle.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
W związku z tym następująca przekształcona forma wektorowa pętli jest legalna , ponieważ kompilator zachowuje sekwencyjne zachowanie każdej iteracji pętli oryginalnej. Innymi słowy, a[i]
jest wykonywany po , jest po a[-1]
b[i]
, a[i]
a wywołanie bar
ma miejsce ostatnio.
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);
}
Nie jest to legalne przeniesienie odwołania *c
do pamięci z pętli, jeśli może ona aliasować za pomocą a[i]
polecenia lub b[i]
. Nie jest to również legalne, aby zmienić kolejność instrukcji wewnątrz jednej oryginalnej iteracji, jeśli przerywa zależność sekwencyjną. Na przykład następująca pętla przekształcona nie jest legalna:
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);
}