openmp krytyczny
Aug 19 2020
Po tym pytaniu dla poniższego kodu ( z przykładu dokumentów MS OpenMP )
// omp_critical.cpp
// compile with: /openmp
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int i;
int max;
int a[SIZE];
for (i = 0; i < SIZE; i++)
{
a[i] = rand();
printf_s("%d\n", a[i]);
}
max = a[0];
#pragma omp parallel for num_threads(4)
for (i = 1; i < SIZE; i++)
{
if (a[i] > max)
{
#pragma omp critical
{
// compare a[i] and max again because max
// could have been changed by another thread after
// the comparison outside the critical section
if (a[i] > max)
max = a[i];
}
}
}
printf_s("max = %d\n", max);
}
Czy mogę usunąć zewnętrzną część, jeśli przetestuję i zrobię
max = a[0];
#pragma omp parallel for num_threads(4)
for (i = 1; i < SIZE; i++)
{
#pragma omp critical
{
// compare a[i] and max again because max
// could have been changed by another thread after
// the comparison outside the critical section
if (a[i] > max)
max = a[i];
}
}
Odpowiedzi
1 cos_theta Aug 19 2020 at 16:53
Możesz, ale to skutecznie skutkuje sekwencyjnym wykonaniem. Wątki ciągle czekają na wejście do sekcji krytycznej, tak że tylko jeden wątek wykonuje w danym momencie treść pętli. W związku z tym uzyskujesz taką samą wydajność (może nawet gorszą ze względu na obciążenie synchronizacji) niż zwykła pętla szeregowa.
Przykład z dokumentów MS jest synchronizowany tylko wtedy, gdy napotkano nową wartość maksymalną. Pozwala to na równoległe przetwarzanie wszystkich niższych wartości aż do tego punktu.
Jak zasugerowano w komentarzach, użyj konstrukcji redukcji.