Sign in to follow this  
deffer

float accuracy on different CPUs (multiplayer physics)

Recommended Posts

Hi. I was wandering whether I could rely on a code being executed on two different CPUs giving me same results (with same every bit) - I need this for accurate physics simulation in a multiplayer game. Let's assume the code is compiled once only, and the two HWs are using the exact same executable. What I'm afraid of, is that newer CPUs have this habit to tweak the code a bit while executing it. I don't know how far a CPU can go with that. Second thing, is possibility of executing instructions with different precision settings. I got this feeling that my app could force it at the beggining of execution, but I'm not sure... Anyway, I'm quite green on the topic, so anybody mind telling me what I should avoid? Or that I'm just going nuts ;)

Share this post


Link to post
Share on other sites
I believe Intel and AMD use different precisions for floating point calculations internally(80 bit vs 64 bit or something), so no I wouldn't count on getting the exactly same result for a calculation

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yeah, I don't think it would remain in-sync for long (if I recall even Age of Empires3 had this problem in multiplayer and they were forced to cut down on the role of their physics in multiplayer). I suppose what you could do then is have the host in charge of the physics and just update the positions of objects as you would any other unit/player...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

x87 should handle everyting as 80 bit extended precision by default. (Intel specifies this is still true in P4 in their instruction set refrence manuals).
Now, the internal format is often more, AMD I think uses 90 bit registers for fp values, 3 bits are meta-data 87 bits are the value.
I don't know Intel's internal format.
For complex instructions that have intermediate results (like square root, reciprocal, I think division) each result is rounded to fit the internal format, and only at the end of the instruction rounded back to 80 bit EP format. That might be able to produce single bit rounding differences in the final result - though it would certainly be an unlikley result.
That small of a difference should not ever effect the value of a single or double, but rounding back to those formats are only done when writing back to memory. So long as it's on the FP stack it will remain in 80 EP format.

I don't know how internal rounding is handled with SSE, but I would think any intermediate results would be rounded to the SSE specified format (double or single) which would eliminate any possible differences in rounding.

Share this post


Link to post
Share on other sites
Well, this really 5uck5, then.
Can I get a second oppinion? [grin]

Now seriously, that means clients would have to be in an exact sync with the host. Frame-to-frame. Receiving positions/velocities/and-what-not all the time.

Isn't it an overkill?

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster

x87 should handle everyting as 80 bit extended precision by default. (Intel specifies this is still true in P4 in their instruction set refrence manuals).
Now, the internal format is often more, AMD I think uses 90 bit registers for fp values, 3 bits are meta-data 87 bits are the value.

[...]
which would eliminate any possible differences in rounding.


So you think I could ignore the differences, as they will be likely rounded and thus disappear?

"Likely" seems not enough, though.
But I could be sending updates from the host every now and then. At least not every turn...

Share this post


Link to post
Share on other sites
Hm.. I've never heard of any differences between Intel and AMDs representations, but even so wouldn't it still work to set a reduced precision in the floating point control word?
But I suppose I wouldn't be too surprised if a few small errors crept in anyway..
Quote:
Original post by deffer
Now seriously, that means clients would have to be in an exact sync with the host. Frame-to-frame. Receiving positions/velocities/and-what-not all the time.

Isn't it an overkill?
It depends, it is what most games do.

A deterministic simulation has the obvious advantage of allowing a network model based on input reflection and only having to transmit a small and constant amount of data per player. Another benefit is having small replay files.

But it's also *much* harder (although not impossible) to compensate for lag with such a metod. Considering that you'll also be forced into using fixed time steps, having to deal with nasty synchronization bugs and probably be forced to use fixed point it'd say it's generally not worth it.
Another annoying issue is that all players are forced to stop their simulation of a single packet from one of the players is dropped. This can be covered up somewhat but becomes a major issue with too many players.

Still.. It does depend a lot on the game type, for an RTS you probably don't have a choice due to the large amount of units in the world.

Share this post


Link to post
Share on other sites
I can tell you with confidence that it will differ between PCs with different procesors. I know of programs where this was a problem. Heck, I've even tried running one of those programs on a different computer and seen the problem for myself!

Sending an update to sync things every now and then might be a good idea. It shouldn't have to be too often though.

The anchient fdiv bug of the early pentiums would go away if you clocked the CPU down a bit aparently. Though I'm not saying that such a thing is still a problem.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Well, this really 5uck5, then.
Can I get a second oppinion? [grin]

Now seriously, that means clients would have to be in an exact sync with the host. Frame-to-frame. Receiving positions/velocities/and-what-not all the time.

Isn't it an overkill?
It doesn't mean you need perfect sync at all. What you do is have clients and host both do the physics, so the client see results right away, but the host has authority over everything and every once in a while (say every 100ms) the host sends the clients the 'real' physics info. This way, clients see results instantly (at least from their own actions), but they never have time to get noticably off.

Share this post


Link to post
Share on other sites
Ok, so I can send a 'real' update every n miliseconds.

But what if the error causes different behaviour in macro-scale. I mean, a character is hit by some other, while on the host sim, it does not at all (quantum theory lurking out, heh). Without immediate validation, even an update every 10ms would be too late in this case, as whole chain of events would be already triggered on client's side.

Are there counter-measures for this?

Share this post


Link to post
Share on other sites
Depending on the game type, you have two choices:
1) It doesn't matter if it is triggered on the client side or not. In FPS, things like seeing a blood splash from a hit that didn't happen isn't too big a deal, so it's fine if you see an extra one every once in a while.

2) It does matter. Essentially, instead of predicting things on the client, you wait for the server to trigger everything. Basically, the server says 'ok X happened' then the client runs the proper effects with periodic corrections from the server. This is only different in that the client waits for verification before starting things.

Edit: Actually, there is a third option:

3) It does mtter, but you don't want to wait. In these situations, you use lag compensation. Essentially, the server keeps a history of everything over the past few seconds, and you use the history plus the latency between each client to know how things looked when the client did something. In this way, you're kind of matching the server to the client, but the server still has authority. The client can show the effect immediately, because as long as the client isn't grossly unsynced (via a cheat, or HUGE latency, etc), the server will be able to verify that the effect would have happened that way and then it sends updates to the other clients.
This option is appealing because it seems to eliminate latency, but it has negative effects also: If somebody is lagging more than you, they can hit you after you ran around a corner (because when they fired, taking their ping into account, you weren't around the corner yet and the server used the history to see that).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hasn't someone somewhere made a program to try a ton of floating point operations and give some sort of hash value as a result to check if processors actually give the same results?

Share this post


Link to post
Share on other sites
I wrote my own arbitrary precision floating point number class which uses only arbitrary-sized-integer arithmetic internaly. This could easily guarantee identical results on ANY platform (if you can handle the performance decrease of course).

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
I wrote my own arbitrary precision floating point number class which uses only arbitrary-sized-integer arithmetic internaly. This could easily guarantee identical results on ANY platform (if you can handle the performance decrease of course).
Why not make it fixed point? Most games really want fixed point anyway (that is, fixed precision in the fraction part), but don't use it because it's a lot more work than using existing types and it will be slower (for a decent amount of precision and range)

Share this post


Link to post
Share on other sites
Quote:
Original post by Extrarius
Quote:
Original post by iMalc
I wrote my own arbitrary precision floating point number class which uses only arbitrary-sized-integer arithmetic internaly. This could easily guarantee identical results on ANY platform (if you can handle the performance decrease of course).
Why not make it fixed point? Most games really want fixed point anyway (that is, fixed precision in the fraction part), but don't use it because it's a lot more work than using existing types and it will be slower (for a decent amount of precision and range)
Yeah I've got a fixed point templated class too, for which I can use the arbitrary-sized-integer class within.
I really mean to post these things one day as I've spent ages perfecting them and never used them outside of the test app.

Share this post


Link to post
Share on other sites
Fixed point?

Weeeh, not using FPU/SSE/.. is a huge step back, don't you think?
And just for the sake of compatibility.

I don't think I would take that as an option. (?)

Share this post


Link to post
Share on other sites
as far as i know the standard is 80 bits of precision internally

however SSE uses 128 bit registers which allows to do 2 operations at once thus with a precision of 64 bits each

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
[...]Weeeh, not using FPU/SSE/.. is a huge step back, don't you think?[...]
How so? Do you really want coordinates becoming less accurate as things get farther away? It seems to me that a uniform accuracy is wanted for coordinates, which is what fixed point gives. Otherwise, things close to the origin are accurate to 0.0001 cm and things miles away are accurate to 10 m, which isn't so great for world coordinates (and many games must get around such things, such as having heirarchial coordinate systems).
Really, I can't wait for 128 bit computers to become standard, because a fixed point system with 88.40 would be perfect - if the unit is meters, the precision is to 1/232 (or to about 12 {12.04} digits ~= the nearest picometer) and it's range is about +/- 2^87 (or about 26 {26.18} digits ~= 100 yottameters). They should be plenty for most games. Of course, this could be implemented now, but with most users having a native word of 32 bits, it wouldn't be very efficient (unless one of the vector instruction sets lets you treat it as 1 register for add/sub/mul/div/etc..?).

Share this post


Link to post
Share on other sites
Quote:
Original post by Extrarius
How so? Do you really want coordinates becoming less accurate as things get farther away? It seems to me that a uniform accuracy is wanted for coordinates, which is what fixed point gives. Otherwise, things close to the origin are accurate to 0.0001 cm and things miles away are accurate to 10 m, which isn't so great for world coordinates (and many games must get around such things, such as having heirarchial coordinate systems).


Well, you don't need to convince me that fixed point arithmetic can be nice as a representation for object's position.
But there's more than +- for floats. There's also */ and it's not trivial to implement (and there's also sqrt).

As for the "step back", I could basically reimplement FPU's functionality in software (not as powerful, but still), but is it the right thing to do (reimplementing things that already are done)?

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
Ok, so I can send a 'real' update every n miliseconds.

But what if the error causes different behaviour in macro-scale. I mean, a character is hit by some other, while on the host sim, it does not at all (quantum theory lurking out, heh). Without immediate validation, even an update every 10ms would be too late in this case, as whole chain of events would be already triggered on client's side.

Are there counter-measures for this?


I'm guessing that this would be a relatively simple thing to avoid. As I see it, the only time you'd have this problem is when comparing two floats that are very similar in value. In that case, you can use an arbitrary tolerance value in every comparison. If that tolerance value is chosen to be greater than any likely drift due to precision loss, then you can effectively eliminate the risk of macro scale differences.

I think.

Share this post


Link to post
Share on other sites
Read This.

Those articles contain important information about network syncronisation.


On the subject of things that must be triggered by the server - simply trigger them by the server. Unless your pings are horrificly large, it won't matter.

The idea is that things that don't matter much, like the client being a little bit off-course, you simulate on both ends, and let the server synch the client up every so often.

Things that are important (and this is game-dependent), you just give the server the authority and just put up with the lag. Things like dying, spawning, etc, that cannot be predicted and would be difficult to synchronise.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this