2010-09-23 14 views
19

Czy OpenMP natywnie obsługuje redukcję zmiennej reprezentującej tablicę?Czy można dokonać redukcji w tablicy z OpenMP?

to będzie działać coś jak poniżej ...

float* a = (float*) calloc(4*sizeof(float)); 
omp_set_num_threads(13); 
#pragma omp parallel reduction(+:a) 
for(i=0;i<4;i++){ 
    a[i] += 1; // Thread-local copy of a incremented by something interesting 
} 
// a now contains [13 13 13 13] 

Idealnie byłoby coś podobnego do równoległej omp za, a jeśli mają wystarczająco dużą liczbę wątków na to sensu, kumulacja nastąpiłaby za pośrednictwem drzewa binarnego.

+7

tylko w Fortranu – Anycorn

+1

Może chcesz wyjaśnić nieco więcej, co chcesz zrobić dokładnie. Pomocny może okazać się kod seryjny. – FFox

+0

Kopanie wokół trochę więcej, brzmi jak "tylko w fortran" jest odpowiedź.Skończyło się na tym, że przydzieliłem pojedynczą dużą liczbę lokalnych kopii poza pętlę, pozwalając wątkom gromadzić się na ich własne kopie wewnątrz pętli for, a następnie gromadząc się w globalnej tablicy po pętli for, wciąż wewnątrz równoległego regionu, wewnątrz krytyczny fragment. –

Odpowiedz

3

Tylko w Fortranie w wersji OpenMP 3.0 i prawdopodobnie tylko z niektórymi kompilatorami.

Zobacz ostatni przykład (przykład 3) na:

http://wikis.sun.com/display/openmp/Fortran+Allocatable+Arrays

+3

Jest to teraz możliwe od OpenMP 4.5; zobacz odpowiedź Chen Jiang poniżej. Zasadniczo musisz określić _array sections_ (sekcja 2.4, s. 44 specyfikacji OpenMP 4.5). Twoja specyfikacja #pragma będzie wyglądać następująco: '#pragma omp równoległa redukcja (+: a [: 4])' Bądź jednak ostrożny, musisz zdać sobie sprawę, że każdy wątek przydzieli własną wersję sekcja tablicowa; jeśli zrobisz to na dużych tablicach z wieloma wątkami, możesz sprawić, że twoja pamięć będzie musiała eksplodować. –

1

OpenMP nie może wykonywać redukcji w odniesieniu do zmiennych tablicowych lub typu struktury (patrz restrictions).

Możesz również przeczytać na temat klauzul private i shared. private deklaruje zmienną jako prywatną dla każdego wątku, gdzie jako shared deklaruje zmienną, która ma być współużytkowana wśród wszystkich wątków. Również znalazłem odpowiedź na to question bardzo przydatne w odniesieniu do OpenMP i tablic.

3

Redukcja matrycy jest teraz możliwa dzięki OpenMP 4.5 dla C i C++. Oto przykład:

#include <iostream> 

int main() 
{ 

    int myArray[6] = {}; 

    #pragma omp parallel for reduction(+:myArray[:6]) 
    for (int i=0; i<50; ++i) 
    { 
    double a = 2.0; // Or something non-trivial justifying the parallelism... 
    for (int n = 0; n<6; ++n) 
    { 
     myArray[n] += a; 
    } 
    } 
    // Print the array elements to see them summed 
    for (int n = 0; n<6; ++n) 
    { 
    std::cout << myArray[n] << " " << std::endl; 
    } 
} 

Wyjścia:

100 
100 
100 
100 
100 
100 

Skompilowałem to GCC 6.2. Możesz zobaczyć, które wspólne wersje kompilatorów obsługują funkcje OpenMP 4.5 tutaj: http://www.openmp.org/resources/openmp-compilers/

Uwaga z powyższego komentarza, że ​​chociaż jest to wygodna składnia, może wywołać wiele kosztów ogólnych z tworzenia kopii każdej sekcji tablicy dla każdego wątku.

0

OpenMP może wykonać tę operację od wersji OpenMP 4.5, a GCC 6.3 (i ewentualnie niższa) obsługuje tę operację. Przykładem programu wygląda następująco:

#include <vector> 
#include <iostream> 

int main(){ 
    std::vector<int> vec; 

    #pragma omp declare reduction (merge : std::vector<int> : omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end())) 

    #pragma omp parallel for default(none) schedule(static) reduction(merge: vec) 
    for(int i=0;i<100;i++) 
    vec.push_back(i); 

    for(const auto x: vec) 
    std::cout<<x<<"\n"; 

    return 0; 
} 

Zauważ, że omp_out i omp_in są specjalne zmienne i że rodzaj declare reduction musi odpowiadać wektor planujesz zmniejszyć dalej.

Powiązane problemy