Udostępnij za pośrednictwem


Rozszerzenie SIMD

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);
    }

Zobacz też

/openmp (Włącz obsługę OpenMP 2.0)