Ich arbeite an einer Anwendung, die Float-Samples im Bereich von -1.0 bis 1.0 zu 16bit konvertiert, um sicherzustellen, dass die Ausgabe der optimierten (SSE) Routinen korrekt ist. Ich habe eine Reihe von Tests geschrieben, die das non ausführt optimierte Version gegen die SSE-Version und vergleicht ihre Ausgabe.
Bevor ich angefangen habe, habe ich bestätigt, dass der SSE-Rundungsmodus auf am nächsten steht.
In meinem Testfall lautet die Formel:
%Vor% In den meisten Fällen sind die Ergebnisse korrekt, aber bei einer bestimmten Eingabe sehe ich einen Fehler für eine Eingabe von -0.8499908447265625
.
Der normale Code rundet das Ergebnis auf -27853
auf, aber der SSE-Code rundet dieses auf -27852
.
Hier ist der verwendete SSE-Code:
%Vor%Selbstenthaltendes Beispiel wie angefordert:
%Vor%Obwohl der SSE-Rundungsmodus standardmäßig auf "Runde auf den nächsten" eingestellt ist, ist es nicht die altbekannte Rundungsmethode, die wir alle in der Schule gelernt haben, sondern eine etwas modernere Variante, bekannt als Rundung des Bankers (auch bekannt als" Unabgestimmtes Runden "," Konvergente Rundung "," Statistische Rundung "," Holländische Rundung "," Gaußsche Rundung "oder" Gerade-Rundung "), die auf den nächsten geraden ganzzahligen Wert gerundet wird. Diese Rundungsmethode ist angeblich aus statistischer Sicht besser als die traditionellere Methode. Sie werden das gleiche Verhalten mit Funktionen wie rint () sehen, und es ist auch das Standard-Rundungsmodus für IEEE-754 .
Beachten Sie auch, dass die Standardbibliotheksfunktion round () die traditionelle Rundungsmethode SSE ROUNDPS
( _mm_round_ps
) verwendet die Rundung des Bankers.
Dies ist das Standardverhalten für die Verarbeitung von all Gleitkommazahlen, nicht nur für SSE. Rund die Hälfte bis zur geraden oder Banker-Rundung ist der standardmäßige Rundungsmodus gemäß dem Standard IEEE 754.
Der Grund dafür ist, dass ein konsistentes Aufrunden (oder Absenken) zu einem halben Punktfehler führt, der sich anhäuft, wenn er nur für eine moderate Anzahl von Operationen angewendet wird. Die halben Punkte können zu einigen ziemlich signifikanten Fehlern führen - signifikant genug, dass sie in Superman 3 zu einem Punkt wurden.
Die runde Hälfte, ob gerade oder ungerade, führt sowohl zu negativen als auch zu positiven Halbpunktfehlern, die sich gegenseitig eliminieren, wenn sie über viele Operationen hinweg angewendet werden.
Dies ist auch in SSE-Operationen wünschenswert. SSE-Operationen werden typischerweise in Signalverarbeitungs- (Audio-, Bild-), Engineering- und statistischen Szenarien verwendet, wo ein konsistenter Rundungsfehler als Rauschen erscheinen würde und zusätzliche Verarbeitung erfordern würde, um (wenn möglich) zu entfernen. Durch die Rundung des Bankers wird sichergestellt, dass dieses Geräusch beseitigt wird
Tags und Links c++ x86 sse intrinsics rounding-error