openmp crítico

Aug 19 2020

Seguindo esta pergunta , para o código abaixo ( de exemplo de documentos 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);
}

Posso remover a parte externa se testar e fazer

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];
    }
}

Respostas

1 cos_theta Aug 19 2020 at 16:53

Você pode, mas isso resulta efetivamente em uma execução sequencial. Os threads estão constantemente esperando para entrar na seção crítica, de forma que apenas um thread execute o corpo do loop por vez. Conseqüentemente, você obtém o mesmo desempenho (talvez até pior devido à sobrecarga de sincronização) do que um loop serial simples.

O exemplo do MS docs só sincroniza se um novo valor máximo for encontrado. Isso permite processar todos os valores inferiores até este ponto em paralelo.

Conforme sugerido nos comentários, use uma construção de redução.