openmp kritisch

Aug 19 2020

Befolgen Sie diese Frage für den folgenden Code ( aus dem Beispiel für MS OpenMP-Dokumente ).

// 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);
}

Kann ich die Außenseite entfernen, wenn testen und tun

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

Antworten

1 cos_theta Aug 19 2020 at 16:53

Sie können, aber dies führt effektiv zu einer sequentiellen Ausführung. Die Threads warten ständig darauf, in den kritischen Abschnitt zu gelangen, sodass jeweils nur ein Thread den Schleifenkörper ausführt. Daher erhalten Sie die gleiche Leistung (möglicherweise sogar schlechter aufgrund des Synchronisationsaufwands) als eine einfache serielle Schleife.

Das Beispiel aus den MS-Dokumenten wird nur synchronisiert, wenn ein neuer Maximalwert festgestellt wurde. Dadurch können alle niedrigeren Werte bis zu diesem Punkt parallel verarbeitet werden.

Verwenden Sie, wie in den Kommentaren vorgeschlagen, ein Reduktionskonstrukt.