Informazioni sulla precisione in virgola mobile e perché la utilizziamo ancora


38

La virgola mobile è sempre stata problematica per la precisione su grandi mondi.

Questo articolo spiega dietro le quinte e offre l'alternativa ovvia: numeri a virgola fissa. Alcuni fatti sono davvero impressionanti, come:

"Ben 64 bit di precisione ti portano alla distanza più lontana di Plutone dal Sole (7,4 miliardi di km) con precisione sub-micrometrica."

Beh, la precisione sub-micrometrica è più di qualsiasi esigenza di fps (per posizioni e persino velocità) e ti consentirebbe di costruire mondi davvero grandi.

La mia domanda è: perché utilizziamo ancora il virgola mobile se il punto fisso presenta tali vantaggi? La maggior parte delle API di rendering e delle librerie di fisica usano il virgola mobile (e ne soffrono gli svantaggi, quindi gli sviluppatori devono aggirarli).

Sono molto più lenti?

Inoltre, come pensi che i motori planetari scalabili come outerra o infinity gestiscano la grande scala? Usano il punto fisso per le posizioni o hanno qualche algoritmo di divisione dello spazio?


3
L'ultimo bit "aggiuntivo" dovrebbe probabilmente essere una domanda separata, quindi quella principale non viene distrutta.
Tetrad,

Voglio capire come forzare il punto fisso ... Il mio gioco ha ogni sorta di strani errori perché Lua usa l'FPU e anche DirectX giocherella con l'FPU ... Ho visto cose come 2 * 9000 = 17995 o 500 * 10 = 4897 è davvero sciocco. Ma l'errore peggiore è probabilmente quello che viene discusso nei forum Ogre3D, dove 1 + 5 = 4.
speeder

3
Non ha giustificato un commento; ma se decidi di usare punti fissi Q-Floats ( en.wikipedia.org/wiki/Q_(number_format) ) sei tuo amico; sono incredibilmente veloci e facili da implementare.
Jonathan Dickinson,

Quindi, per riassumere, dovrei rimanere con i punti mobili (se lavoro in Java o Python)? - Gastón 26 minuti fa
Gastón

Risposte:


20

Se mi consentirai una spina spudorata, ti darò un esempio da un gioco reale su cui sto lavorando (link video YouTube).

Il gioco ha un mondo infinito, generato proceduralmente su un motore fisico. Utilizza un virgola mobile a precisione singola. Dopo alcune centinaia di metri di spazio di gioco, iniziano a sorgere problemi di precisione (e peggiorano progressivamente quanto più si ottiene dall'origine).

La mia soluzione? Ogni 200 m circa, muovo il mondo intero indietro di 200 m verso l'origine (se ti interessa trovare e provare uno dei prototipi sul mio sito e far apparire l'overlay di debug [w] orld, puoi vedere che ciò accade).

Perché non usare il punto fisso? O doppia precisione? Invece di precisione singola? Perché tutto il resto utilizza una virgola mobile di precisione singola!

Il motore fisico che sto usando lo usa, XNA lo usa, i dati che vengono caricati sulla scheda grafica sono formattati come virgola mobile a precisione singola. Anche la lingua stessa è progettata per funzionare con numeri in virgola mobile - la scrittura e (soprattutto) la lettura 0.5fè molto più semplice di 0x80000000L.

È semplicemente una questione di ciò che è più facile in pratica. E il chiaro vincitore sta conoscendo i problemi di precisione in virgola mobile e sta scrivendo abbastanza semplici funzioni "sposta il mondo a zero" (o implementa il partizionamento dello spazio o qualunque cosa si adatti al tuo gioco).

E, infine, un altro esempio: Orbiter è il gioco (simulazione, davvero) che deve davvero preoccuparsi della precisione. Non solo nello spazio ma anche nel tempo (accelerazione del tempo più corpi orbitanti - non vogliono che cadano dal cielo, ora). Utilizza anche numeri in virgola mobile e impiega un hack per mantenere la stabilità.


Mi sono sempre chiesto se per alcune applicazioni potrebbe essere più semplice spostare tutto il resto e mantenere il "player" all'origine. Interessante vedere che non sono l'unico!
dash-tom-bang,

Mi piace il tuo ragionamento. Vorrei solo sottolineare che quando si tratta di giochi che coinvolgono il punto fisso di rete sembra avere meno stranezze / deviazioni (la previsione del cliente è più accurata).
Jonathan Dickinson,

Non capisco molto bene la tua tesi. E comunque perché le lingue non hanno ancora implementato il punto fisso? Naturalmente questo sembra essere un motivo per essere disegnato per usare i float, ma ciò non spiega perché il punto fisso non sia stato implementato ovunque.
jokoon

@jokoon Ho pensato che la mia risposta fosse abbastanza chiara. Perché il punto fisso non è implementato ovunque? Basta guardare a Wikipedia: "Pochissimi linguaggi per computer includono il supporto integrato per valori a virgola fissa, perché per la maggior parte delle applicazioni, le rappresentazioni in virgola mobile binarie o decimali sono in genere più semplici da usare e sufficientemente accurate ". Un buon designer sa cosa omettere - e qualcosa che duplica la funzionalità in un modo che rende davvero facile per un programmatore spararsi ai piedi è un buon candidato.
Andrew Russell,

Concordato. I processori di oggi eseguono le istruzioni in virgola mobile molto facilmente, le istruzioni hanno un throughput eccellente e la maggior parte ha una latenza di pochi cicli più lunga rispetto alle istruzioni intere.
Doug65536,

11

Primo: sì, sono significativamente più veloci. Anche se riesci a far funzionare il punto fisso con la stessa velocità di una FPU "normale", il punto mobile reale ha istruzioni vantaggiose come fsel per interrompere la ramificazione o SIMD per lavorare su molti galleggianti contemporaneamente. Le GPU usano anche il virgola mobile, almeno nelle loro interfacce rivolte all'utente.

In secondo luogo, 64 bit ti portano abbastanza lontano anche in virgola mobile - la maggior parte delle persone ne usa ancora 32, ma il vantaggio principale è che si ridimensiona. Quella scala a virgola fissa ha una precisione fissa. Che tu stia misurando il sole su Plutone o dall'altra parte della strada, ottieni la stessa precisione. Il virgola mobile ti darà risultati molto più accurati quando tutti i valori coinvolti sono più piccoli. Poiché le librerie di fisica generica dovrebbero funzionare almeno in modo passabile con molti giochi su scale diverse - e alcuni giochi possono avere scale molto diverse - devono usare un tipo di numero che funzioni su più scale.


5

Un altro punto importante da sottolineare è che i galleggianti non sono così imprecisi come la gente qui sembra pensare. Un float a 32 bit ha 24 bit di precisione intera intera. Ciò significa che è almeno accurato come un valore in virgola fissa a 24 bit per un determinato intervallo. Mentre i float diventano meno precisi tanto più grande diventa il valore, un valore in punti fissi semplicemente traboccerà e si avvolgerà a un certo punto. Ridurre la precisione è un migliore fallback. I galleggianti possono anche traboccare, ma molto, molto più tardi. Mi piacerebbe vedere i tuoi volti quando il tuo mondo si avvolge improvvisamente a -2 ^ 31 a causa del trabocco di punti fissi.

I valori in virgola mobile a 64 bit hanno 53 bit di precisione intera, quindi sono davvero accurati.


I valori in virgola mobile non effettivamente traboccano; se il risultato di un calcolo è troppo grande per essere rappresentato, il risultato è Infinito positivo o negativo.
Ananas

3

In un contesto FPS, i valori a virgola fissa potrebbero essere effettivamente una responsabilità. Più vicino allo zero in virgola mobile è più preciso. È solo a grande distanza che diventa più preferibile il punto fisso. La risposta è semplicemente che dipende dal contesto.

In qualcosa come una galassia puoi usare i frame di riferimento. Usa una scala enorme per i sistemi solari e quindi usa il centro del Sole (o un punto simile) come punto di origine per qualsiasi cosa all'interno del sistema. Usando questo sistema puoi avere la tua torta e mangiarla, per così dire, e non è difficile da immaginare.

IIRC, lo sviluppatore di Infinity ha dichiarato di aver ripetutamente ripetuto problemi su larga scala in una delle sue interviste.


È improbabile che in qualsiasi gioco sia necessaria la precisione "vicino allo zero" del virgola mobile. Se hai un'unità di un metro, 10 bit di precisione ti offrono una precisione inferiore al millimetro e ti consentono comunque di modellare oltre 4000 km in ogni direzione se sei bloccato con valori a 32 bit. Se hai bisogno di più precisione di un millimetro, puoi spostare alcuni bit in più, di sicuro. Passare a valori di 64 bit in un gioco spaziale ti darebbe un sistema solare (o più?) Con precisione costante su tutto il volume.
dash-tom-bang,

Infatti. Ed è per questo che useresti il ​​Sole di un sistema solare come punto di riferimento in un mondo delle dimensioni di una galassia! Il punto è che il metodo scelto per gestire la precisione non porta nulla alla tabella in nessun modo. È discutibile, quindi potresti anche usare quello a cui è sintonizzata la tua libreria / hardware.
Rushyo,

Per inciso, ho lavorato su un gioco in cui abbiamo dovuto modellare oltre 4000 km in ogni direzione. Per compatibilità con il codice in altri progetti, ha dovuto usare 32 bit per le posizioni. Non è un problema teorico, date le esigenze commerciali poste sul riutilizzo del codice e le dimensioni dei mondi di gioco oggi.

1

Se non l'hai ancora fatto, dai un'occhiata al tutorial di Planet Rendering su GameDev.net. Per quanto riguarda la divisione dello spazio, una soluzione è quella di mantenere due variabili di posizione separate: una scala macro e una scala micro. Funziona abbastanza bene (testato).

La soluzione esatta dipende da come prevedi di gestire le distanze estreme nel motore: pianifichi gate di salto o compressione del tempo?


1

Uno dei motivi è che l'aritmetica in virgola mobile è "abbastanza buona" (o almeno lo è stata), produce rapidamente risultati abbastanza precisi.

Fintanto che sei a conoscenza dei limiti dell'aritmetica in virgola mobile e cambi i tuoi algoritmi per affrontarli (vedi la risposta di Andrew Russell), otterrai un codice che "funziona".


-1

Sto scrivendo un gioco. Nel mio gioco / programma, disegno un'astronave all'origine usando una macchina fotografica abbastanza fissa e il mio pianeta disegno usando una macchina fotografica separata. E queste due cose si occupano del problema per me, ma il mio pianeta non è ancora molto dettagliato. Per quanto riguarda la soluzione menzionata da Andrew Russell sul fatto di spostare il mondo (e presumo che la telecamera e i suoi abitanti tornino all'origine), non ci proverei davvero se pensassi di rendere il gioco un gioco in rete. Se spostassi il mondo sull'applicazione server in base ai movimenti di ciascun client, il mondo finirebbe per lottare per una posizione. E prenderebbe la sua posizione in continuazione da tutti coloro che suonano, il che sarebbe un enorme problema tecnico.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.