Jaka jest różnica między tymi dwoma?
[ZA]
#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}
[B]
#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
Jaka jest różnica między tymi dwoma?
[ZA]
#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}
[B]
#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
Odpowiedzi:
Myślę, że nie ma żadnej różnicy, jeden jest skrótem dla drugiego. Chociaż Twoja dokładna implementacja może radzić sobie z nimi inaczej.
Połączone konstrukcje równoległego współdzielenia pracy są skrótem do określania konstrukcji równoległej zawierającej jedną konstrukcję współdzielenia pracy i żadnych innych instrukcji. Dozwolone klauzule to suma klauzul dozwolonych dla konstruktów równoległych i współdzielonych.
Zaczerpnięto z http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf
Specyfikacje dla OpenMP są tutaj:
Te są równoważne.
#pragma omp parallel
spawnuje grupę wątków, podczas gdy #pragma omp for
dzieli iteracje pętli między zwołanymi wątkami. Możesz zrobić obie rzeczy naraz dzięki #pragma omp parallel for
dyrektywie fused .
#pragma omp parallel for
dyrektywy. Powinna być jakaś różnica.
Oto przykład użycia separacji parallel
i for
tutaj . Krótko mówiąc, może być używany do dynamicznego przydzielania prywatnych tablic wątków OpenMP przed wykonaniem for
cyklu w kilku wątkach. Niemożliwe jest wykonanie tej samej inicjalizacji w parallel for
przypadku.
UPD: W przykładzie z pytaniem nie ma różnicy między jedną a dwiema pragmami. Ale w praktyce możesz sprawić, by zachowanie bardziej świadome wątku było oddzielone dyrektywy równoległe i dla dyrektyw. Na przykład jakiś kod:
#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
}
Chociaż obie wersje konkretnego przykładu są równoważne, jak już wspomniano w innych odpowiedziach, nadal istnieje między nimi niewielka różnica. Pierwsza wersja zawiera niepotrzebną ukrytą barierę, napotkaną na końcu „omp for”. Drugą ukrytą barierę można znaleźć na końcu obszaru równoległego. Dodanie „nowait” do „omp for” spowodowałoby, że te dwa kody byłyby równoważne, przynajmniej z punktu widzenia OpenMP. Wspominam o tym, ponieważ kompilator OpenMP może wygenerować nieco inny kod dla obu przypadków.
Widzę zupełnie inne środowiska wykonawcze, gdy biorę pętlę for w g ++ 4.7.0 i używam
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 (no openmp
) działa w 79 ms. kod „równoległy dla” działa w 29 ms. Jeśli pominąć for
i użyć #pragma omp parallel
, pędy uruchomieniowe do 179ms, które jest wolniejsze niż kod seryjny. (maszyna ma współbieżność Hw 8)
kod prowadzi do libgomp
#pragma omp for
pętli nie ma w ogóle wielowątkowego udostępniania pętli. Ale i tak nie był to przypadek OP, spróbuj ponownie z dodatkowym #pragma omp for
wewnątrz #pragm omp parallel
i powinien działać podobnie (jeśli nie taki sam) jak #pragma omp parallel for
wersja.
Odpowiedzi jest oczywiście mnóstwo, ale ta odpowiada na nie bardzo ładnie (ze źródłem)
#pragma omp for
deleguje tylko części pętli dla różnych wątków w bieżącym zespole. Zespół to grupa wątków wykonujących program. Na początku programu zespół składa się tylko z jednego członka: wątku głównego, który uruchamia program.Aby utworzyć nowy zespół wątków, musisz określić słowo kluczowe parallel. Można to określić w otaczającym kontekście:
#pragma omp parallel { #pragma omp for for(int n = 0; n < 10; ++n) printf(" %d", n); }
i:
Co to jest: równolegle, za i zespół
Różnica między równolegle, równolegle dla i dla jest następująca:
Zespół to grupa wątków, które są aktualnie wykonywane. Na początku programu zespół składa się z jednego wątku. Konstrukcja równoległa dzieli bieżący wątek na nowy zespół wątków na czas trwania następnego bloku / instrukcji, po czym zespół łączy się z powrotem w jeden. for dzieli pracę pętli for pomiędzy wątki obecnego zespołu.
Nie tworzy wątków, a jedynie dzieli pracę pomiędzy wątki aktualnie wykonującego zespołu. parallel for to skrót dla dwóch poleceń naraz: parallel i for. Parallel tworzy nowy zespół i dzieli ten zespół do obsługi różnych części pętli. Jeśli twój program nigdy nie zawiera konstrukcji równoległej, nigdy nie ma więcej niż jednego wątku; główny wątek, który uruchamia program i uruchamia go, tak jak w programach nie obsługujących wątków.
schedule(static, chunk)
klauzuli w dyrektywie for, pojawia się problem. Kod działa dobrze, ale kiedy wywołuję ten kod z programu MPI, uruchamia się w nieskończonej pętli. Licznik pętli wynosi zero we wszystkich iteracjach tej pętli. Mam licznik pętli zdefiniowany jako prywatny w#pragma omp parallel
dyrektywie. 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 ma to znaczenie. Nie mam pojęcia, czy harmonogram powoduje problem.