Moin!
Mal kurz zurück zum eigentlichen Thema. Ich versuche seit geraumer Zeit, wirklich mit OpenMP klarzukommen, habe aber noch grundlegende Probleme.
Das Augenscheinlichste ist, dass eine parallele Berechnung andere Ergebnisse liefert, als eine in nur einem Thread ausgeführte.
Hier mal ein simpel gehaltener Beispielcode:
Code:
#include "stdio.h"
#include <omp.h>
#include <math.h>
#include <limits.h>
#include <stdint.h>
int main(int argc, char *argv[]) {
int k,inf=100000000;
double sum, revsum;
sum = 0.0;
revsum = 0.0;
#pragma omp parallel for
for( k=1 ; k<=inf ; k++) {
sum += 1.0/pow(k,(double)2);
}
#pragma omp parallel for
for( k=inf ; k>=1 ; k--) {
revsum += 1.0/pow(k,(double)2);
}
printf("%.52f\n%.52f\n",sum,revsum);
return 0;
}
Hier das Ergebnis:
Code:
herakles@schlepptop ~ $ gcc test.c -Wall
test.c: In Funktion »main«:
test.c:15:0: Warnung: #pragma omp parallel wird ignoriert [-Wunknown-pragmas]
test.c:19:0: Warnung: #pragma omp parallel wird ignoriert [-Wunknown-pragmas]
herakles@schlepptop ~ $ ./a.out
1.6449340578345750252253765211207792162895202636718750
1.6449340568482264668404013718827627599239349365234375
Dass bei der umgedrehten Berechnung ein anderes Ergebnis herauskommt, habe ich inzwischen gelernt (siehe
diesen Thread) - Rundungsfehler offenbar. Darum geht es auch nicht. Interessanter ist folgendes:
Wenn ich das nun mit openmp kompilieren, wird das Ergebnis beider Berechnungen anders:
Code:
herakles@schlepptop ~ $ gcc test.c -Wall -fopenmp
herakles@schlepptop ~ $ ./a.out
1.6422920408720118601308968209195882081985473632812500
1.644934052758408649097532361338380724191665649414062
Bei der ersten Berechnung ist die Differenz schon recht groß, ich kopiere die beiden zum Vergleich mal in die nächsten zwei Zeilen:
1.6449340578345750252253765211207792162895202636718750 OHNE OpenMP
1.6422920408720118601308968209195882081985473632812500 MIT OpenMP
Da ist also bei der Verwendung von OpenMP schon eine Differenz in der dritten Nachkommastelle zu erkennen - nur weil ich auf 2 Prozessoren arbeite?
Bis jetzt habe ich das noch nicht vollkommen nachvollziehen können.
Zwei Fragen dazu:
1. Entsteht das unterschiedliche Ergebnis (mit und ohne OpenMP), weil ohne OpenMP die Berechnungen immer in der gleichen Reihenfolge durchgeführt werden und deshalb immer exakt DERSELBE Rundungsfehler auftritt, wenn man aber in willkürlicher Reihenfolge (also mit OpenMP) die Berechnungen macht, dann treten die Rundungsfehler in unterschiedlicher Reihenfolge auf, was zu einem abweichenden Ergebnis führt?
Zitat dazu von
linux-mag.com
Very briefly, the way the round-off error accumulates in these calculations does have an impact upon the final results. Running this sum in the other direction, which most people would normally do, accumulates error in a different order, leading to a different result. That is, when you change the order of your floating point computations, you will change the round-off error accumulation. It it possible to observe a catastrophic loss of accuracy, impacting first and second digits of a summation like this, by not being aware of these issues. But that’s a topic for another time.
2. Wie macht man den obigen Beispielcode "besser", "richtiger" oder minimiert, ja bestenfalls löscht den Fehler? Geht das überhaupt?
Grübelnde Grüße
Herakles