3 ms·
There is a persistent myth that floating point is non-deterministic and therefore cannot be used for "lockstep" multiplayer games. This may have been true in t
by throwaway858 5y ago
There is a persistent myth that floating point is non-deterministic and therefore cannot be used for "lockstep" multiplayer games.
This may have been true in the 90s because of buggy C compilers, but has long not been the case.
you can use 32 bit or 64 bit floating point and your code will be completely determistic across all modern CPUs and operating systems and even across most programming languages.
The only thing you need to avoid are trig functions (sin, cos) since different platforms have different implementations. so you use your own implementation for these functions(for games you can an approximation which will be even faster than the library implementation). many platforms have an identical sqrt function, but this should be thoroughly tested.
Also if you are running on an intel CPU on 32 bit OS (rare nowadays) you need to call a function at the start of your program to disable 80 bit extended fp.
- protastus 5y ago> There is a persistent myth that floating point is non-deterministic and therefore cannot be used for "lockstep" multiplayer games. Indeed, on all systems I've used, FP is deterministic in the strict sense that running the same code twice on the same platform (with identical HW and SW stack) will produce the same results. But the results may change depending on: - programming language - libraries used and their versions - underlying silicon - whether SIMD is used - FPU flags - compiler flags (example: ffast-math affects many things behind the scenes, as does /fp:fast, including things that dramatically affect accuracy like the use of approximate reciprocal instructions) - bugs affecting all of the above At scale, this matrix becomes difficult to track and control. So it shouldn't be a surprise that reproducibility is an issue, and this myth persists.
- throwaway858 5y ago> But the results may change depending on: > - programming language As I mentioned in my comment, this is part of the myth. most programming languages have the exact same semantics regarding floating point and if you port an algorithm between them you will get identically deterministic results. this is true for at least c/c++, java, c#, python, javascript, and many more. - libraries used and their versions As I mentioned in my comment, this is the only true part of the myth. sqrt should be safe, but trig functions will be different. for games, a lot of them use there own "fast" versions anyway, so not a problem. - underlying silicon nothing to worry about here. All modern CPUs have identical IEE754 semantics (except intel 32 bit which I addressed in my original comment) - whether SIMD is used Again, nothing to worry about here, whether it is hand coded SIMD assembly, or compiler generated, you will always get identical and portable results. the compiler is obligated to ensure this for autogenerated SIMD. - FPU flags not relevant on any system from the last 10 years - compiler flags (example: ffast-math affects many things behind the scenes, as does /fp:fast, including things that dramatically affect accuracy like the use of approximate reciprocal instructions) ffast-math by definition introduces imprecise semantics so simply don't use it - bugs affecting all of the above compilers (and CPUs!) may have been buggy decades ago but in the modern age floating point is extensively tested. I would be very surprised to see a floating point related bug in a compiler or programming language from the last 10 years
- benibela 5y agoI still have these problems > - programming language I decided to not use C, because it is unsafe, and write all my code in Pascal. Now the FreePascal double parsing does not work correctly For one, it always uses 80-bit float. Even if parsing a double, then it rounds the 80-bit float to double after parsing, so the last bit is usually wrongly rounded. They refuse to fix it, because it is easier to maintain just one 80-bit float parsing function than multiple parsing functions for different types. >- libraries used and their versions So I moved to someone's double parsing library. It just did not work. It simply lacked the algorithms required for full double precision parsing But they were happy to fix it >- FPU flags After fixing it, that double parsing library still did not work ... on 32-bit Although the library was implementing the correct operations. Turned out FreePascal compiles 64-bit using SSE, and 32-bit using FPU which was set to 80-bit precision In reverse, formatting the double as string is also hard and ambiguous. FreePascal usually prints two decimal digits more than required (in the new implementation. They still had a broken implementation a handful years ago). I wrote my own implementation that prints the shortest decimal using arbitrary precision arithmetic, but that is really slow. (I tried to use a library, but that did not have enough precision, and after they tried to fix it, it is completely broken.)