2016-06-30 7 views
1

Mein Code mit Openmp, der "Reduktion" verwendet, gibt die gleichen Ergebnisse von Lauf zu Lauf nicht zurück.Reduzierung in Openmp gibt verschiedene Ergebnisse mit der gleichen Anzahl von Threads in meinem Code zurück

Fall 1: Verwendung von "reduction"

sum = 0; 
omp_set_num_threads(4); 
#pragma omp parallel for reduction(+:sum) 
for(ii = 0; ii < 100; i++) 
    sum = sum + func(ii); 

mit func (ii) hat Nebenwirkungen. In der Tat verwendet func (ii) eine andere Funktion von calcul(), die zu einer Race-Bedingung in paralleler Ausführung führen kann. Ich denke, dass die Funktion calcul() ein Grund für dieses Problem sein kann. Allerdings verwende ich "kritisch", die Ergebnisse sind immer die gleichen, aber diese Lösung ist nicht gut für die Leistung.

Fall 2. Platz: "kritische" mit

sum = 0; 
#pragma omp parallel for 
for(ii = 0; ii < 100; i++) 
{ 
    #pragma omp critical 
    sum = sum + func(ii); 
} 

mit der func (ii) Funktion

func(int val) 
{ 
    read_file(val); 
    calcul(); /*calculate something from reading_file(val)*/ 
    return val_fin; 
} 

Bitte helfen Sie mir, es zu lösen?

Vielen Dank!

+0

Es sieht aus wie das Problem nicht mit dem 'reduction' Teil ist aber in einem Rennen Zustand innerhalb der' func (ii) 'Anruf. Da wir den Code für 'func' oder' calcul' nicht sehen können, ist es schwer mehr zu sagen. –

+0

Hallo Dan, meine Funktion (ii) ist auch kompliziert, dann kann ich Ihnen ihre Kopie vorstellen func (ii) {... lesen (ii); ... Kalkül(); ... Rückgabewert; } – hamalo

+0

Sie müssen nicht die gesamte Funktion posten, gerade genug, um Ihr Problem * neu zu erstellen und Ihre Frage klarzustellen. Siehe [Erstellen eines minimalen, vollständigen und überprüfbaren Beispiels] (http://stackoverflow.com/help/mcve). –

Antwort

0

Selbst wenn alles in dem Code korrekt ist, können Sie immer noch unterschiedliche Ergebnisse aus der OpenMP Reduktion erhalten aufgrund der Assoziativität der Operationen (Additionen). Um dasselbe Ergebnis für eine bestimmte Anzahl von Threads reproduzieren zu können, müssen Sie die Reduktion selbst implementieren, indem Sie die Teilsumme jedes Threads in einem gemeinsam genutzten Array speichern. Nach dem parallelen Bereich kann der Master-Thread diese Ergebnisse hinzufügen. Dieser Ansatz impliziert, dass die Threads immer die gleichen Iterationen ausführen, d. H. Eine statische Planungsrichtlinie.

Verwandte Frage: Order of execution in Reduction Operation in OpenMP

+0

Danke Phadjido: D – hamalo

1

Der Grund, warum Sie schlechte Leistung im zweiten Fall bekommen, ist der gesamte Schleifenkörper ist in einem critical, so dass es eigentlich nichts parallel ausführen kann.

Da Sie sagen, es gibt einige Wettlaufbedingungen in der calcul Funktion, ziehen Sie in Betracht, einen critical Abschnitt gerade auf dieser Linie innerhalb func setzen. Auf diese Weise können die Dateien parallel gelesen werden (dies kann die E/A sein, die Ihre Ausführung ohnehin verlangsamt).

Wenn die Leistung immer noch schlecht ist, müssen Sie in die verschachtelte calcul-Funktion schauen und versuchen, die Rennbedingungen zu identifizieren.

Grundsätzlich möchten Sie alle critical Abschnitte so weit wie möglich nach unten drücken oder sie vollständig beseitigen. Wenn es um sehr einfache Aktualisierungen für gemeinsam genutzte Variablen geht, können Sie in einigen Fällen stattdessen das Pragma OpenMP atomic verwenden, das eine bessere Leistung bietet, aber viel weniger flexibel ist.

+0

Danke @Dan. Ich konzentriere mich auf die gleichen Ergebnisse, "kritisch" kann diese Frage beantworten, aber es ist nicht gut für die Leistung. Ich werde versuchen, mit Ihrer Unterstützung – hamalo

Verwandte Themen