Über Gleitkomma-Präzision und warum verwenden wir sie immer noch?


38

Fließkommazahlen waren für große Welten immer problematisch.

Dieser Artikel erklärt die Hintergründe und bietet die offensichtliche Alternative - Festkommazahlen. Einige Fakten sind wirklich beeindruckend, wie:

"64 Bit Präzision bringen Sie mit Submikrometer-Präzision zur weitesten Entfernung von Pluto von der Sonne (7,4 Milliarden km)."

Nun, die Präzision im Submikrometerbereich ist mehr als alle FPS-Anforderungen (für Positionen und sogar Geschwindigkeiten) und es würde Ihnen ermöglichen, wirklich große Welten zu bauen.

Meine Frage ist, warum wir immer noch Fließkomma verwenden, wenn Festkomma solche Vorteile hat. Die meisten Rendering-APIs und Physikbibliotheken verwenden Gleitkommazahlen (und weisen Nachteile auf, sodass Entwickler diese umgehen müssen).

Sind sie so viel langsamer?

Wie gehen skalierbare Planetenmotoren wie Outerra oder Infinity mit dem großen Maßstab um? Verwenden sie feste Punkte für Positionen oder haben sie einen Algorithmus zur Raumteilung?


3
Das letzte "zusätzliche" Bit sollte wahrscheinlich eine separate Frage sein, damit das Hauptbit nicht abgelenkt wird.
Tetrad

Ich möchte herausfinden, wie man einen festen Punkt erzwingt ... Mein Spiel weist alle möglichen seltsamen Fehler auf, da Lua die FPU verwendet und DirectX auch mit der FPU spielt ... Ich habe Dinge wie 2 * 9000 = 17995 oder 500 * 10 gesehen = 4897 es ist wirklich albern. Aber der schlimmste Fehler ist wahrscheinlich einer, der in Ogre3D-Foren diskutiert wird, wo 1 + 5 = 4.
Speeder

3
Hat einen Kommentar nicht gerechtfertigt; Aber wenn Sie sich für die Verwendung von Q-Floats mit Festkomma entscheiden ( en.wikipedia.org/wiki/Q_(number_format ), sind Sie mit uns befreundet. Sie sind lächerlich schnell und einfach zu implementieren.
Jonathan Dickinson

Also, um es zusammenzufassen, sollte ich mich an Gleitkommazahlen halten (wenn ich in Java oder Python arbeite)? - Gastón vor 26 Minuten
Gastón

Antworten:


20

Wenn Sie mir einen schamlosen Stecker erlauben, gebe ich Ihnen ein Beispiel von einem echten Spiel, an dem ich arbeite (YouTube-Videolink).

Das Spiel hat eine unendliche, prozedural erzeugte Welt auf einer Physik-Engine. Es verwendet Gleitkommazahlen mit einfacher Genauigkeit. Nach ein paar hundert Metern Spielraum beginnen Präzisionsprobleme aufzutreten (und werden immer schlimmer, je weiter Sie vom Ursprung entfernt sind).

Meine Lösung? Etwa alle 200 m bewege ich die ganze Welt um 200 m in Richtung des Ursprungs zurück (wenn Sie einen der Prototypen auf meiner Site suchen und ausprobieren und das [w] orld-Debug-Overlay aufrufen möchten, können Sie dies beobachten).

Warum nicht Fixpunkt verwenden? Oder doppelte Präzision? Statt einfacher Präzision? Weil alles andere Gleitkommazahlen mit einfacher Genauigkeit verwendet!

Die von mir verwendete Physik-Engine verwendet sie, XNA verwendet sie, und die Daten, die auf die Grafikkarte geladen werden, werden als Gleitkommazahlen mit einfacher Genauigkeit formatiert. Sogar die Sprache selbst ist darauf ausgelegt, mit Gleitkommazahlen zu arbeiten - Schreiben und (was noch wichtiger ist) Lesen 0.5fist viel einfacher als 0x80000000L.

Es geht einfach darum, was in der Praxis einfacher ist. Und der klare Gewinner ist sich der Probleme mit der Fließkommapräzision bewusst und schreibt ziemlich einfache Funktionen zum Zurücksetzen der Welt auf Null (oder zum Implementieren einer Raumaufteilung oder was auch immer für Ihr Spiel geeignet ist).

Und schließlich noch ein Beispiel - Orbiter ist ein Spiel (Simulation, wirklich), bei dem es wirklich um Präzision geht. Nicht nur im Raum, sondern auch in der Zeit (Zeitbeschleunigung plus umlaufende Körper - ich möchte nicht, dass sie jetzt vom Himmel fallen). Es verwendet auch Gleitkommazahlen und verwendet einen Hack , um die Stabilität aufrechtzuerhalten.


Ich habe mich immer gefragt, ob es für manche Anwendungen einfacher sein könnte, alles andere zu verschieben und den "Player" am Ursprung zu halten. Interessant zu sehen, ich bin nicht der einzige!
Dash-Tom-Bang

Ich mag deine Argumentation. Ich möchte nur darauf hinweisen, dass bei Spielen mit Netzwerkfestpunkt weniger Macken / Abweichungen auftreten (die Vorhersage der Kunden ist genauer).
Jonathan Dickinson

Ich verstehe dein Argument nicht sehr gut. Und übrigens, warum haben Sprachen noch keinen Fixpunkt implementiert? Das scheint natürlich ein Grund zu sein, Schwimmer zu verwenden, aber das erklärt nicht, warum Fixpunkt nicht überall implementiert wurde.
jokoon

@jokoon Ich dachte, meine Antwort war ganz klar. Warum ist Fixpunkt nicht überall implementiert? Schauen Sie sich nur Wikipedia an: "Nur sehr wenige Computersprachen bieten eine integrierte Unterstützung für Festkommawerte, da binäre oder dezimale Gleitkommadarstellungen für die meisten Anwendungen normalerweise einfacher zu verwenden und genau genug sind ." Ein guter Designer weiß, was er auslassen muss - und etwas, das die Funktionalität auf eine Weise dupliziert, die es einem Programmierer wirklich leicht macht, sich selbst in den Fuß zu schießen, ist ein guter Kandidat.
Andrew Russell

Einverstanden. Heutige Prozessoren führen Gleitkommabefehle sehr leicht aus, die Befehle haben einen ausgezeichneten Durchsatz und die meisten haben nur wenige Zyklen längere Latenz als Ganzzahlbefehle.
Doug65536

11

Erstens - ja, sie sind bedeutend schneller. Selbst wenn Sie Festkomma so schnell wie eine "normale" FPU zum Laufen bringen können, verfügt ein echter Gleitkomma über vorteilhafte Anweisungen wie fsel, um die Verzweigung zu beenden, oder SIMD, um auf vielen Gleitkommas gleichzeitig zu arbeiten. GPUs verwenden auch Gleitkommazahlen, zumindest in ihren Benutzeroberflächen.

Zweitens erreichen Sie mit 64 Bit auch einen ziemlich hohen Fließkommawert - die meisten Leute verwenden immer noch 32, aber der Hauptvorteil ist, dass es skaliert. Diese Festpunktskala hat eine feste Genauigkeit. Egal, ob Sie die Sonne nach Pluto messen oder auf der anderen Straßenseite, Sie erhalten die gleiche Präzision. Gleitkommawerte liefern viel genauere Ergebnisse, wenn alle beteiligten Werte kleiner sind. Da von generischen Physikbibliotheken erwartet wird, dass sie mit vielen Spielen in verschiedenen Maßstäben zumindest passabel funktionieren - und einige Spiele selbst möglicherweise sehr unterschiedliche Maßstäbe haben -, müssen sie eine Art Zahl verwenden, die in vielen Maßstäben funktioniert.


5

Ein weiterer wichtiger Punkt ist, dass Schwimmer nicht so ungenau sind, wie die Leute hier zu denken scheinen. Ein 32-Bit-Float verfügt über 24 Bit mit vollständiger Ganzzahlgenauigkeit. Dies bedeutet, dass es für einen bestimmten Bereich mindestens so genau wie ein 24-Bit-Festpunktwert ist. Während Floats mit zunehmendem Wert ungenauer werden, läuft ein fester Punktwert einfach über und dreht sich irgendwann um. Eine Verringerung der Genauigkeit ist ein besserer Rückfall. Schwimmer können auch überlaufen, aber weit, weit später. Ich würde gerne Ihre Gesichter sehen, wenn sich Ihre Welt aufgrund eines Überlaufs an festen Punkten plötzlich auf -2 ^ 31 dreht.

64-Bit-Gleitkommawerte haben eine Ganzzahlgenauigkeit von 53 Bit und sind daher sehr genau.


Fließkommawerte laufen nicht wirklich über. Wenn das Ergebnis einer Berechnung zu groß ist, um dargestellt zu werden, ist das Ergebnis positiv oder negativ unendlich.
Ananas

3

In einem FPS-Kontext können Festpunktwerte tatsächlich eine Verbindlichkeit sein. Gleitkommazahl nahe Null ist genauer. Es wird nur über große Entfernungen der Fixpunkt vorgezogen. Die Antwort ist einfach, dass es vom Kontext abhängt.

In so etwas wie einer Galaxie können Sie Referenzrahmen verwenden. Verwenden Sie eine große Skala für die Sonnensysteme und verwenden Sie dann den Sonnenmittelpunkt (oder einen ähnlichen Punkt) als Ursprungspunkt für alles innerhalb des Systems. Mit diesem System können Sie Ihren Kuchen haben und ihn sozusagen essen, und es ist nicht schwer, ihn sich vorzustellen.

IIRC, der Entwickler von Infinity, gab an, dass er in einem seiner Interviews ständig Skalenprobleme durchgearbeitet habe.


Es ist unwahrscheinlich, dass Sie in einem Spiel die Genauigkeit von Gleitkomma "nahe Null" benötigen. Wenn Sie eine Ein-Meter-Einheit haben, erhalten Sie mit einer Genauigkeit von 10 Bit eine Genauigkeit im Submillimeterbereich und können dennoch über 4000 km in jede Richtung modellieren, wenn Sie mit 32-Bit-Werten feststecken. Wenn Sie mehr Präzision als einen Millimeter benötigen, können Sie sicher ein paar Bits mehr verschieben. Wenn Sie in einem Weltraumspiel auf 64-Bit-Werte wechseln, erhalten Sie ein Sonnensystem (oder mehr?) Mit konstanter Präzision über das gesamte Volumen.
Dash-Tom-Bang

Tatsächlich. Und deshalb würden Sie die Sonne eines Sonnensystems als Bezugspunkt in einer galaxiengroßen Welt verwenden! Der Punkt ist, dass die von Ihnen gewählte Methode für den Umgang mit Präzision nichts auf den Tisch bringt. Es ist strittig, daher können Sie auch diejenige verwenden, auf die Ihre Bibliothek / Hardware abgestimmt ist.
Rushyo

Ich habe übrigens an einem Spiel gearbeitet, bei dem wir über 4000 km in jede Richtung modellieren mussten. Für die Kompatibilität mit Code in anderen Projekten mussten 32 Bit für Positionen verwendet werden. Angesichts der kommerziellen Anforderungen an die Wiederverwendung von Code und der Größe der heutigen Spielwelten ist dies kein theoretisches Problem.

1

Wenn du es noch nicht getan hast, solltest du das Planet Rendering Tutorial auf GameDev.net definitiv ausprobieren. Was die Raumteilung betrifft, besteht eine Lösung darin, zwei separate Positionsvariablen beizubehalten - eine Makroskala und eine Mikroskala. Das funktioniert ganz gut (getestet).

Die genaue Lösung hängt davon ab, wie Sie mit extremen Entfernungen im Motor umgehen möchten. Planen Sie Sprungtore oder Zeitkomprimierung?


1

Einer der Gründe ist, dass Gleitkomma-Arithmetik "gut genug" ist (oder zumindest war), und ziemlich genaue Ergebnisse schnell liefert.

Solange Sie die Einschränkungen der Gleitkomma-Arithmetik kennen und Ihre Algorithmen entsprechend anpassen (siehe Andrew Russells Antwort), werden Sie Code produzieren, der "funktioniert".


-1

Ich schreibe ein Spiel. In meinem Spiel / Programm zeichne ich ein Raumschiff am Ursprung mit einer ziemlich festen Kamera und meinen Planeten zeichne ich mit einer separaten Kamera. Und diese beiden Dinge erledigen das Problem für mich, aber mein Planet ist noch nicht sehr detailliert. Was die Lösung angeht, die Andrew Russell über das Bewegen der Welt erwähnt hat (und ich gehe davon aus, dass die Kamera und ihre Bewohner zum Ursprung zurückkehren), würde ich das wirklich nicht versuchen, wenn Sie jemals vorhaben, das Spiel zu einem vernetzten Spiel zu machen. Wenn Sie die Welt auf der Serveranwendung basierend auf den Bewegungen der einzelnen Clients verschieben würden, würde die Welt am Ende um eine Position kämpfen. Und würde seine Position die ganze Zeit von allen Spielern einnehmen, was eine große Panne wäre.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.