HI,
Ich habe etwas gemischten C / C ++ - Code mit einigen intensiven numerischen Berechnungen entwickelt. Wenn ich unter Linux und Mac OS X kompiliert habe, bekomme ich nach Abschluss der Simulation sehr ähnliche Ergebnisse. In Windows kompiliert das Programm auch, aber ich bekomme sehr unterschiedliche Ergebnisse und manchmal scheint das Programm nicht zu funktionieren.
Ich habe GNU-Compiler in allen Systemen verwendet. Ein Freund empfiehlt mir, -rounding-math hinzuzufügen und jetzt scheint die Windows-Version stabiler zu funktionieren, aber Linux und Os X, ihre Ergebnisse, ändern sich überhaupt nicht.
Können Sie eine andere Option empfehlen, um mehr Übereinstimmung zwischen Win- und Linux / OSX-Versionen zu erreichen?
Danke
P.D. Ich habe auch -O0 (keine Optimierungen) ausprobiert und -m32
angegebenIch kann nicht mit der Implementierung in Windows sprechen, aber Intel-Chips enthalten 80-Bit-Gleitkommaregister und können eine höhere Genauigkeit als die im IEEE-754-Gleitkomma-Standard angegebene angeben. Sie können versuchen, diese Routine im main () Ihrer Anwendung (auf Intel-Chipplattformen) aufzurufen:
%Vor%Ich denke dies unterscheidet sich von den von @ Alok diskutierten Rundungsmodi.
Es gibt vier verschiedene Arten von Rundungen für Gleitkommazahlen: Runden in Richtung Null, Runden, Runden und Runden auf die nächste Zahl. Je nach Compiler / Betriebssystem kann der Standard auf verschiedenen Systemen unterschiedlich sein. Informationen zum programmgesteuerten Ändern der Rundungsmethode finden Sie unter fesetround
. Es ist durch den C99 Standard spezifiziert, kann aber für Sie verfügbar sein.
Sie können auch die Option -ffloat-store
gcc ausprobieren. Dadurch wird verhindert, dass gcc 80-Bit-Gleitkommawerte in Registern verwendet.
Wenn sich Ihre Ergebnisse in Abhängigkeit von der Rundungsmethode ändern und die Unterschiede signifikant sind, bedeutet dies, dass Ihre Berechnungen möglicherweise nicht stabil sind. Ziehen Sie in Betracht, eine Intervallanalyse durchzuführen oder eine andere Methode zu verwenden, um das Problem zu finden. Weitere Informationen finden Sie unter Wie nutzlos sind Mindless-Assessments von Roundoffs in der Gleitkommaberechnung? (pdf) und Die Fehler bei der Überprüfung von Fließkomma-Berechnungen (ACM-Link, aber Sie können PDF von vielen bekommen Orte, wenn das für dich nicht funktioniert).
Zusätzlich zu den von den Benutzern erwähnten Laufzeit-Rundungseinstellungen können Sie die Visual Studio-Compilereinstellungen unter Eigenschaften & gt; C ++ & gt; Codegenerierung & gt; Gleitkomma-Modell. Ich habe Fälle gesehen, in denen das Setzen von "Fast" zu einem schlechten numerischen Verhalten führen kann (z. B. wenn iterative Methoden nicht konvergieren).
Die Einstellungen werden hier erklärt: Ссылка
Die IEEE- und C / C ++ - Standards lassen einige Aspekte der Fließkomma-Mathematik unspezifiziert. Ja, das genaue Ergebnis des Hinzufügens zu Floats wird bestimmt, aber eine kompliziertere Berechnung ist nicht möglich. Wenn Sie beispielsweise drei Gleitkommazahlen hinzufügen, kann der Compiler die Auswertung mit Float-Genauigkeit, doppelter Genauigkeit oder höher durchführen. Wenn Sie drei Doppelpunkte hinzufügen, kann der Compiler die Auswertung mit doppelter Genauigkeit oder höher durchführen.
In VC ++ wird standardmäßig die x87-FPU-Genauigkeit verdoppelt. Ich glaube, dass gcc es mit 80-Bit-Genauigkeit verlässt. Weder ist deutlich besser, aber sie können leicht andere Ergebnisse geben, vor allem, wenn Ihre Berechnungen instabil sind. Insbesondere "winzig + groß - groß" kann zu sehr unterschiedlichen Ergebnissen führen, wenn Sie zusätzliche Präzisionsbits haben (oder wenn sich die Reihenfolge der Auswertung ändert). Die Implikationen der variierenden Zwischenpräzision werden hier diskutiert:
Die Herausforderungen des deterministischen Gleitkommas werden hier diskutiert:
Fließkomma-Mathematik ist schwierig. Sie müssen herausfinden, wann Ihre Berechnungen abweichen und den generierten Code untersuchen, um zu verstehen, warum. Nur dann können Sie entscheiden, welche Maßnahmen zu ergreifen sind.