2009-09-19 18 views

Odpowiedz

50

Nie sądzę, nie ma żadnej różnicy, jedno jest skrótem dla innych. Chociaż twoja dokładna implementacja może potraktować je inaczej.

Połączone równolegle konstrukty współdzielenia to skrót określenie równolegle konstrukt zawierający jedną Worksharing skonstruować i żadnych innych instrukcji. Dopuszczalne klauzule są połączone klauzulami dozwolonymi dla elementów współrzędnych równoległych i podziału pracy.

Zrobione z http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

Specyfikacje dla OpenMP tutaj:

http://openmp.org/wp/openmp-specifications/

44

te są równoważne.

#pragma omp parallel spawns grupę wątków, a #pragma omp for dzieli pętli iteracji między zarodkami wątków. Możesz wykonywać obie te czynności jednocześnie za pomocą połączonej dyrektywy #pragma omp parallel for.

+0

W moim kodzie używam tej właśnie struktury. Jednak gdy używam klauzuli 'schedule (static, chunk)' dla dyrektywy, pojawia się problem. Kod działa dobrze, ale kiedy wywołuję ten kod z programu MPI, uruchamia się on w nieskończoną pętlę. Licznik pętli wynosi zero we wszystkich iteracjach tej pętli. Licznik pętli jest zdefiniowany jako prywatny w dyrektywie '#pragma omp parallel'. Nie mam pojęcia, dlaczego zawodzi tylko wtedy, gdy MPI wywołuje kod. Jestem pewien, że każdy proces MPI działa na innym procesorze klastra, jeśli to ma znaczenie. Nie wiem, czy przyczyną problemu jest harmonogram. –

+0

To samo działa dobrze, gdy używam dyrektywy '#pragma omp parallel dla'. Powinna istnieć jakaś różnica. –

+1

Aktualizacja: Jak się okazuje, obserwuję ten problem tylko wtedy, gdy używam klauzuli harmonogramu, więc myślę, że to nie zależy od tego, czy używam połączonego paralela dla dwóch różnych dyrektyw. –

2

widzę jaskrawo różne czasy pracy, gdy biorę pętli for w g ++ 4.7.0 i korzystania

std::vector<double> x; 
std::vector<double> y; 
std::vector<double> prod; 

for (int i = 0; i < 5000000; i++) 
{ 
    double r1 = ((double)rand()/double(RAND_MAX)) * 5; 
    double r2 = ((double)rand()/double(RAND_MAX)) * 5; 
    x.push_back(r1); 
    y.push_back(r2); 
} 

int sz = x.size(); 

#pragma omp parallel for 

for (int i = 0; i< sz; i++) 
    prod[i] = x[i] * y[i]; 

kod seryjny (bez openmp) przebiega w 79 ms. kod "równoległy dla" działa w 29 ms. Jeśli pominę for i użyję #pragma omp parallel, środowisko wykonawcze wykona do 179 ms, , co jest wolniejsze niż kod seryjny. (Maszyna ma hw współbieżności z 8)

łącza kod do libgomp

+2

Myślę, że to dlatego, że równolegle omp wykonuje pętlę w osobnym wątku bez dzielenia go na wątki, więc główny wątek oczekuje na zakończenie drugiego wątku. czas poświęcony na synchronizację. – Antigluk

+6

To dlatego, że bez '#pragma omp for' nie ma w ogóle wielowątkowego współdzielenia pętli. Ale to i tak nie było w przypadku OP, spróbuj ponownie z dodatkowym '#pragma omp for' wewnątrz' #pragm omp równoległym' i powinno działać podobnie (jeśli nie to samo) jak '#pragma omp parallel for' version' . –

+0

Widzę tę odpowiedź jako najlepszą, ponieważ pokazuje, że nie są one "równoważne" –

19

Oto przykład użycia oddzielone parallel i forhere. W skrócie można go wykorzystać do dynamicznej alokacji prywatnych macierzy OpenMP przed wykonaniem cyklu for w kilku wątkach. Nie można wykonać tego samego inicjowania w przypadku parallel for.

UPD: W pytającym przykładzie nie ma różnicy między pojedynczą pragmą a dwoma pragmami. Ale w praktyce można wytworzyć więcej wątków z oddzielnymi równoległymi i dla dyrektyw. Niektóre kod na przykład:

#pragma omp parallel 
{ 
    double *data = (double*)malloc(...); // this data is thread private 

    #pragma omp for 
    for(1...100) // first parallelized cycle 
    { 
    } 

    #pragma omp single 
    {} // make some single thread processing 

    #pragma omp for // second parallelized cycle 
    for(1...100) 
    { 
    } 

    #pragma omp single 
    {} // make some single thread processing again 

    free(data); // free thread private data 
} 
4

Choć obie wersje są równoważne konkretnym przykładzie, jak już wspomniano w innych odpowiedzi, jest jeszcze jedna mała różnica między nimi. Pierwsza wersja zawiera niepotrzebną niejawną barierę, napotkaną na końcu "omp for". Drugą ukrytą barierę można znaleźć na końcu równoległego obszaru. Dodanie "nowait" do "omp for" spowodowałoby, że oba kody byłyby równoważne, przynajmniej z perspektywy OpenMP.Wspominam o tym, ponieważ kompilator OpenMP może generować nieco inny kod dla dwóch przypadków.