openmp критический

Aug 19 2020

Следуя этому вопросу , для кода ниже ( из примера документов 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);
}

Могу ли я снять снаружи, если протестирую и сделаю

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

Ответы

1 cos_theta Aug 19 2020 at 16:53

Вы можете, но это фактически приводит к последовательному выполнению. Потоки постоянно ждут входа в критическую секцию, так что только один поток выполняет тело цикла за раз. Следовательно, вы получаете ту же производительность (возможно, даже хуже из-за накладных расходов на синхронизацию), чем простой последовательный цикл.

Пример из документации MS синхронизируется, только если обнаружено новое максимальное значение. Это позволяет обрабатывать все более низкие значения до этого момента параллельно.

Как предложено в комментариях, используйте редукционную конструкцию.