openmp
OpenMP-Reduzierungen
Suche…
Bemerkungen
Alle 4 Versionen sind gültig, aber sie veranschaulichen verschiedene Aspekte einer Reduktion.
Standardmäßig muss das erste Konstrukt mit der reduction
bevorzugt werden . Dies ist nur möglich, wenn einige Probleme explizit identifiziert werden, sodass möglicherweise eine der drei Alternativen untersucht wird.
Annäherung an PI Hand-Crafting der #pragma omp-Reduktion
int i;
int n = 1000000;
double area = 0;
double h = 1.0 / n;
#pragma omp parallel shared(n, h)
{
double thread_area = 0; // Private / local variable
#pragma omp for
for (i = 1; i <= n; i++)
{
double x = h * (i - 0.5);
thread_area += (4.0 / (1.0 + x*x));
}
#pragma omp atomic // Applies the reduction manually
area += thread_area; // All threads aggregate into area
}
double pi = h * area;
Die Threads werden in der #pragma omp-Parallele erzeugt. Jeder Thread verfügt über einen unabhängigen / privaten Thread-Bereich, in dem die teilweise Addition gespeichert wird. Die folgende Schleife wird mit #pragma omp for unter den Threads verteilt. In dieser Schleife berechnet jeder Thread seinen eigenen Thread-Bereich, und nach dieser Schleife aggregiert der Code den Bereich nacheinander atomar durch
Annäherung von PI unter Verwendung von Reduktionen basierend auf #pragma atomic
double area;
double h = 1.0 / n;
#pragma omp parallel for shared(n, h, area)
for (i = 1; i <= n; i++)
{
double x = h * (i - 0.5);
#pragma atomic
area += (4.0 / (1.0 + x*x));
}
pi = h * area;
In diesem Beispiel führen alle Threads eine Teilmenge des Iterationszählers aus und sammeln sich atomar im Bereich der gemeinsam genutzten Variablen an, wodurch sichergestellt wird, dass keine Aktualisierungen verloren gehen. Wir können hier das #pragma-Atom verwenden, da die gegebene Operation (+ =) atomar ausgeführt werden kann, was die Lesbarkeit im Vergleich zur Verwendung des #pragma omp-kritisch vereinfacht.
Annäherung von PI unter Verwendung von Reduktionen basierend auf #pragma omp kritisch
double area;
double h = 1.0 / n;
#pragma omp parallel for shared(n, h, area)
for (i = 1; i <= n; i++)
{
double x = h * (i - 0.5);
#pragma omp critical
{
area += (4.0 / (1.0 + x*x));
}
}
double pi = h * area;
In diesem Beispiel führen alle Threads eine Teilmenge des Iterationszählers aus und sammeln sich atomar im Bereich der gemeinsam genutzten Variablen an, wodurch sichergestellt wird, dass keine Aktualisierungen verloren gehen.
Annäherung von PI mit #pragma omp Reduktionsklausel
int i;
int n = 1000000;
double area = 0;
double h = 1.0 / n;
#pragma omp parallel for shared(n, h) reduction(+:area)
for (i = 1; i <= n; i++)
{
double x = h * (i - 0.5);
area += (4.0 / (1.0 + x*x));
}
pi = h * area;
In diesem Beispiel führen alle Threads eine Teilmenge des Iterationszählers aus. Jeder Thread hat seine lokale private Kopie des Bereichs und am Ende des parallelen Bereichs wenden sie alle die Additionsoperation (+) an, um den endgültigen Wert für den Bereich zu erzeugen.