Floating Point Determinism

BlitzMax Forums/BlitzMax Programming/Floating Point Determinism

Scienthsine(Posted 2011) [#1]
Is there a blitzmax builtin way of setting floating point internal precision and round modes? If not, has anyone looked into what would be required to add a couple of functions to do this?

I was considering doing a quick rts in bmax, and I'd like to be able to use floats/doubles. With a lockstep networked game, sending only inputs, this needs to be exactly deterministic for all players involved in a game.

A few links to relevant information regarding the issue:
http://www.christian-seiler.de/projekte/fpmath/
http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/

It would be best to have determinism across all 3 platforms, but this may be too difficult to achieve. At the very least setting the rounding mode, and internal precision should all the same executable to perform deterministically from one one processor to another.d

In addition to this, are there any other determinism problems in bmax? I remember some sort of rand() bug in one of the blitz languages causing some sort of problem... vaguely...


ImaginaryHuman(Posted 2011) [#2]
How about implementing your own fixed point math with, say, numbers up to 24-bit and 8-bit decimal part? Or numbers up to 65536 and decimal part with same resolution?


Scienthsine(Posted 2011) [#3]
Well, that's an option. I would rather not though. That seems like it would introduce many headaches. The range would be significantly decreased. The computational overhead could be a ton. Without operator overloading and neat syntactical tricks, it would be ugly. I would have to implement complex trigonometric functions, or use tables. Finally, I really dislike the idea of having to mock up something that I could easily find a library for in another language... just to use my 'RAD' language.

So, although other solutions exist, they are _far_ from ideal compared to being able to set the rounding and precision in blitz. Now, they do have the advantage of being completely deterministic, even across platforms and processors... and possibly the best choice due to that. I still wish I had the option to set these in Blitz though.


Czar Flavius(Posted 2011) [#4]
My rts game uses its own fixed point. It's relatively basic but the game isn't heavy on physics. I have look up tables for sin, cos tan that have 3600 elements and the angle of "900" corrosponds to the angle of 90.0 and the angle of "2795" is the angle 279.5. I have a support program that generates these tables and dumps to a file which is incbinned in the main executable, so every exe will always generate the same values.

Each pixel is subdivided into 10, so a position of 5000, 5000 is drawn at pixel 500, 500. 5005, 5005 is halfway between 500, 500 and 501, 501. You could convert this to float in order to position the draw image. In retrospect, I think 10 is too high a subdivision. It also means positions need to be stored in longs unless the map is small.

Is there a better way? I don't know, but I'd be interested if there were. Don't use arbitrary position libraries, they are super too slow.

The built-in rand function isn't deterministic across platforms but Brucey has a random module replacement that is. It's handy to have two randoms (Brucey's and a third party one), and use the second one for unimportant things such as graphical candy, particle effects.

Last edited 2011


ImaginaryHuman(Posted 2011) [#5]
Working with fixed point is easy, all you have to remember is to do a Shl or Shr when you want to convert it to an integer value? The rest of the time you do integer math on it which is possibly faster than doing floating point?


Scienthsine(Posted 2011) [#6]
Well, also when doing multiplies or divides you need to do some 'shifts'. Though not as simple as just shl/shr, as those are binary shifts ofcourse.

I'm just spoiled I guess. I get alot of ideas like using randomly generated maps with resources being destributed by different noise functions. I tend to make everything into a formula, and it just seems a pain to have to break those up into discrete steps worrying about overflows and crap at each step.

Anyway thanks for the responses guys.


ImaginaryHuman(Posted 2011) [#7]
I don't think you can really change the float precision because that'd be changing the float format itself which is IEEE standard and made to work natively with the cpu or whatever?


Scienthsine(Posted 2011) [#8]
Ehh read the links ;)

The specification has provisions allowed for using higher internal precision when performing operations. So basically if you add two floats then multiply by another float, then the cpu can store the intermediate result of the add in a higher precision format, reducing the accumulated error from rounding and truncating between every operation. Intel has 80 bit registers and operatons for example.


BlitzSupport(Posted 2011) [#9]
Weirdly, I found myself reading the Gaffer articles tonight (having got a really crude UDP server/client going), coming across floating-point determinism and remembering this thread...


The specification has provisions allowed for using higher internal precision when performing operations



Not exactly an answer, but Mark posted about this some time ago, which you might find of interest. (See Floyd's post four up too.)


Scienthsine(Posted 2011) [#10]
Yep, thats caused by the same problem.

How hard would it be to try to impliment _controlfp?
http://msdn.microsoft.com/en-us/library/e9b52ceh(v=vs.80).aspx

Mingw includes it too under it's math.h

Blitzmax uses mingw right? Is it possible to use this function somehow? I'm not really sure at what point this function is implimented.

Ofcourse there may still be issues with the optimizer reordering float instructions, which due to rounding are not fully communtative. Meaning we may still get different answers depending on platform, small code changes, debug or release mode, etc...

I'm fine with this though, aslong as the same executable always runs the same. Ofcourse with a cross platform system like ming, I wonder if it would optimize similarly...