Myths About Floating-Point Numbers (2021)
12 points by riki
12 points by riki
I’ve been working on a demo recording feature for my game. The basic premise of a demo file is that you record the initial conditions, and then after that you only record the sequence of player inputs that happened afterwards, yielding a much smaller file size than an equivalent video recording. For demo files to work correctly, your engine has to be fully deterministic.
One thing I was wondering about is: isn’t floating point imprecision / non-determinism gonna beat me here? I mean, Valve does it in the Source Engine somehow, and it’s a common feature in older games such as Quake or Doom, so it can’t be that bad.
And I stumbled upon this article while researching how deterministic floating point numbers can be between different machines. Apparently, they aren’t—not weird considering that every hardware vendor will necesarily have their own FPU designs—but I wonder to what degree this affects my use case.
The main things that can screw up determinism are roughly speaking the things that -ffast-math messes around with.
associativity: floating point arithmetic is not associative so for determinism you have to be sure your compiler doesn’t re-associate arithmetic
denormal numbers: historically, very small floats have been difficult to implement correctly and efficiently; that’s no longer a problem, but you need to make sure they aren’t accidentally disabled
rounding mode also needs to be consistent.
As well as all that, if you’re using any libm functions such as trigonometry, they must behave the same in all builds of your code. You might have to choose a specific libm to use instead of relying on the system libm: you don’t want a change of algorithm inside sin() or cos() to screw up determinism.
Besides what fanf said, you might also need to turn off / defeat “excess precision”. Basically: in some cases the compiler might find it faster to do intermediate steps of a computation in a higher precision than the type you asked for, and only convert back to the lower-precision type when the time comes to store the result back to memory. In many cases that’s a good thing (you get a better result and it’s faster!) but the “in some cases” can be a source of non-determinism between builds.
Historically the poster child for this was the x87 FPU, which carries out operations to 80-bit precision internally, even when your in-memory format is 32-bit or 64-bit. A lot of floating-point work on x86 these days is carried out using SSE/AVX rather than x87, but not all — and x87 isn’t the only case where it’s possible, anyway.
Are you sure only the inputs are saved in the source Engine?
Because while player inputs might be better than the absolute states, both are light years ahead of video recording.
Afaik the Source Engine doesn’t (only) use deltas, but the absolute states. So I save the position and orientation of the player instead of the change.
You can obviously mix both approaches. I don’t need to constantly record what equipment I’m holding.
Yeah, I read up a bit more on the Valve developer wiki after posting this and realised that Source indeed doesn’t actually use the user input method for objects:
Demos will record physics and object interactions as they are in the demo and not simulate new physics when playing back, to avoid physical objects from moving differently.
Still I think my point stands, given that the feature does effectively the same thing. However, for my game, I think I want to simulate the world either way, because I like the value it could bring into bug reproducibility.
Oh, I’m definitely not disagreeing here. I love this approach.
I played around with this approach for network communication in games.
Basically you only send player interactions and predict the other players interactions.
You keep the oldest verified state and a new unverified state with all deltas. as soon as you get a contradiction in your assumption you rewind from old to new. You need to set an “age” limit for how far the oldest verified state can be, but otherwise the idea is quite similar to your demo recording.