Szukaj…


Parametry

Klauzula Parametr
private Rozdzielana przecinkami lista zmiennych prywatnych
firstprivate Jak private , ale inicjowany do wartości zmiennej przed wejściem do pętli
lastprivate Jak private , ale zmienna otrzyma wartość odpowiadającą ostatniej iteracji pętli przy wyjściu
reduction operator redukcji : rozdzielona przecinkami lista odpowiednich zmiennych redukcji
schedule static , dynamic , guided , auto lub runtime z opcjonalnym rozmiarem porcji po śpiączce dla 3 pierwszych
collapse Liczba idealnie zagnieżdżonych pętli do zwinięcia i równoległości
ordered Informuje, że niektóre części pętli będą musiały być utrzymywane w kolejności (części te zostaną konkretnie zidentyfikowane za pomocą niektórych ordered klauzul wewnątrz ciała pętli)
nowait Usuń domyślną barierę istniejącą domyślnie na końcu konstrukcji pętli

Uwagi

Znaczenie klauzuli schedule jest następujące:

  • static[,chunk] : Dystrybucja statyczna (co oznacza, że dystrybucja odbywa się przed wejściem do pętli) iteracje pętli w partiach wielkości chunk w sposób okrągły. Jeśli chunk nie jest określona, porcje są tak równe, jak to możliwe, a każdy wątek otrzymuje co najwyżej jeden z nich.
  • dynamic[,chunk] : Dystrybucja iteracji pętli wśród wątków o partiach chunk wielkości z pierwszego-come-first-służył polityce, dopóki nie szczątków wsadowych. Jeśli nie zostanie określony, chunk jest ustawiona na 1
  • guided[,chunk] : jak dynamic ale z partiami, których rozmiary stają się coraz mniejsze, do 1
  • auto : Pozwól kompilatorowi i / lub bibliotece wykonawczej zdecydować, co najlepiej pasuje
  • runtime : decyzja zostanie podjęta w czasie wykonywania za OMP_SCHEDULE zmiennej środowiskowej OMP_SCHEDULE . Jeśli w czasie wykonywania zmienna środowiskowa nie zostanie zdefiniowana, zostanie zastosowane domyślne planowanie

Domyślnym schedule jest definiowanie implementacji . W wielu środowiskach jest static , ale może być również dynamic lub bardzo dobrze auto . Dlatego uważaj, aby twoja implementacja nie polegała w sposób dorozumiany na nim bez wyraźnego ustawienia.

W powyższych przykładach zastosowaliśmy stopioną postać parallel for lub parallel do . Konstrukcji pętli można jednak używać bez łączenia jej z dyrektywą parallel , w postaci #pragma omp for [...] lub !$omp do [...] samodzielnej dyrektywy w regionie parallel .

Tylko w wersji Fortran zmienne indeksu pętli sparaliżowanej pętli są domyślnie zawsze private . Dlatego nie ma potrzeby jawnego uznawania ich za private (chociaż nie jest to błąd).
W przypadku wersji C i C ++ indeksy pętli są jak wszystkie inne zmienne. Dlatego jeśli ich zasięg wykracza poza równoległe pętle (pętle) (co oznacza, że nie są zadeklarowane jak for ( int i = ...) ale raczej jak int i; ... for ( i = ... ) wówczas muszą zostać uznane za private .

Typowy przykład w C.

#include <stdio.h>
#include <math.h>
#include <omp.h>

#define N 1000000

int main() {
    double sum = 0;

    double tbegin = omp_get_wtime();
    #pragma omp parallel for reduction( +: sum )
    for ( int i = 0; i < N; i++ ) {
        sum += cos( i );
    }
    double wtime = omp_get_wtime() - tbegin;

    printf( "Computing %d cosines and summing them with %d threads took %fs\n",
            N, omp_get_max_threads(), wtime );

    return sum;
}

W tym przykładzie po prostu obliczamy 1 milion cosinusów i sumujemy ich wartości równolegle. Wykonujemy również czas wykonania, aby sprawdzić, czy równoległość ma jakikolwiek wpływ na wydajność. Wreszcie, ponieważ mierzymy czas, musimy upewnić się, że kompilator nie zoptymalizuje wykonanej pracy, więc udajemy, że wykorzystujemy wynik, po prostu zwracając go.

Ten sam przykład w Fortran

program typical_loop
    use omp_lib
    implicit none
    integer, parameter :: N = 1000000, kd = kind( 1.d0 )
    real( kind = kd ) :: sum, tbegin, wtime
    integer :: i

    sum = 0

    tbegin = omp_get_wtime()
    !$omp parallel do reduction( +: sum )
    do i = 1, N
        sum = sum + cos( 1.d0 * i )
    end do
    !$omp end parallel do
    wtime = omp_get_wtime() - tbegin

    print "( 'Computing ', i7, ' cosines and summing them with ', i2, &
        & ' threads took ', f6.4,'s' )", N, omp_get_max_threads(), wtime

    if ( sum > N ) then
        print *, "we only pretend using sum"
    end if
end program typical_loop

Tutaj ponownie obliczamy i gromadzimy 1 milion cosinusów. Mierzymy czas w pętli i aby uniknąć niepożądanej optymalizacji kompilatora, udajemy, że wykorzystujemy wynik.

Kompilowanie i uruchamianie przykładów

Na 8-rdzeniowym komputerze z systemem Linux używającym GCC w wersji 4.4, kody C można skompilować i uruchomić w następujący sposób:

$ gcc -std=c99 -O3 -fopenmp loop.c -o loopc -lm
$ OMP_NUM_THREADS=1 ./loopc
Computing 1000000 cosines and summing them with 1 threads took 0.095832s
$ OMP_NUM_THREADS=2 ./loopc
Computing 1000000 cosines and summing them with 2 threads took 0.047637s
$ OMP_NUM_THREADS=4 ./loopc
Computing 1000000 cosines and summing them with 4 threads took 0.024498s
$ OMP_NUM_THREADS=8 ./loopc
Computing 1000000 cosines and summing them with 8 threads took 0.011785s

W przypadku wersji Fortran daje:

$ gfortran -O3 -fopenmp loop.f90 -o loopf
$ OMP_NUM_THREADS=1 ./loopf
Computing 1000000 cosines and summing them with  1 threads took 0.0915s
$ OMP_NUM_THREADS=2 ./loopf
Computing 1000000 cosines and summing them with  2 threads took 0.0472s
$ OMP_NUM_THREADS=4 ./loopf
Computing 1000000 cosines and summing them with  4 threads took 0.0236s
$ OMP_NUM_THREADS=8 ./loopf
Computing 1000000 cosines and summing them with  8 threads took 0.0118s

Dodanie dwóch wektorów przy użyciu równoległego OpenMP do konstrukcji

void parallelAddition (unsigned N, const double *A, const double *B, double *C)
{
    unsigned i;

    #pragma omp parallel for shared (A,B,C,N) private(i) schedule(static)
    for (i = 0; i < N; ++i)
    {
        C[i] = A[i] + B[i];
    }
}

W tym przykładzie dodano dwa wektor ( A i B do C ), OMP_NUM_THREADS zespół wątków (określony na OMP_NUM_THREADS przez zmienną OMP_NUM_THREADS OMP_NUM_THREADS) i przypisując każdemu wątkowi część pracy (w tym przykładzie przypisaną statycznie przez schedule(static) wyrażenie).

Patrz sekcja uwag w odniesieniu do opcjonalności private(i) .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow