Maybe I have a solution of linux floating point problem

Maybe I have a solution of linux floating point problem

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
memarko
Posts: 2
Joined: 21 Feb 2006, 20:28

Maybe I have a solution of linux floating point problem

Post by memarko »

1.The problem may be in different calculation order:
Does somebody want to do the hard work and change all the souce code and put "(" and ")" in each floating point formula.

2.The problem is different accuracy:

a)Problem can be 80 bit format for better accuracy in internal calculations in floating point unit of proccessor:
Calculations are in one of the OS saved in memory and restored in processor register again. Something like that,

Maybe If each operation would be a different expression(y=a+b*c; -->s=b*c;y=s+a; ), would work. But I dont think so.
Another solution is:
For each operation we have to write function. This can be made in easy way by making it with aritmetric-logic operations. If it is too much floating point operations for this synchronisation, processor will not be able to do so much work because it wont use floating point unit. How much is too much? It depends of the percent synchronisational dependent floating point operation in the whole game and CPU ussage.

b)Problem may be 32 bit or 64 bit floating point fomat.
This can checked with Ansi C function sizeof(name of the type).

I dont know much about the concept of the game. So I can be wrong about the solutions.
greenail
Spring Developer
Posts: 80
Joined: 13 Dec 2005, 20:16

Post by greenail »

TVO and I did some testing and we currently hold the following 2 theorys

1. the heightmap causes sync problems
2. buildtime differences cause economy problems

We played several games and the x positions were exactly the same for specific units. Also of note was the fact that some of the de-syncs came back into "sync" after a period of time.
malric
Posts: 521
Joined: 30 Dec 2005, 22:22

Post by malric »

@memarko I think problems can be even more complex

For example in Visual Studio

Code: Select all

void f(double b) {
double a = (float)b;
is not equivalent (under certain flags, optimizations and value of b) to

Code: Select all

void f(doube b) {
float t = (float)b;
double a = t;
(I have found this while searching between something very similar to Spring problems)

Another problem would be the implementation of mathematical functions like sin,cos and etc. If by chance on one compiler the result is rounded and on the other is floored.... the final result will be very slightly different.

About 1) I think the order of operation is common to VC/gcc, so paranthesis would be of no use.

About 2) b) I think that sizes for float and double are 4 and 8. (now I have only gcc to test)
FrantzX
Posts: 5
Joined: 17 May 2005, 23:32

Post by FrantzX »

We could just choose a precision to our floats (ie number of zeros after the demical point) as use intergal numbers.

example
1.86f / 3.45f = 0.53913043478260869565217391304348
18600 / 34500 =53.913043478260869565217391304348 --> 54
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Maybe I have a solution of linux floating point problem

Post by Tobi »

memarko wrote:1.The problem may be in different calculation order:
Does somebody want to do the hard work and change all the souce code and put "(" and ")" in each floating point formula.
This won't solve it. If the compiler executes the operations in a different order, putting "(" ")" around it won't help (if it would help, the compiler is broken).
memarko wrote:2.The problem is different accuracy:

a)Problem can be 80 bit format for better accuracy in internal calculations in floating point unit of proccessor:
Calculations are in one of the OS saved in memory and restored in processor register again. Something like that,

Maybe If each operation would be a different expression(y=a+b*c; -->s=b*c;y=s+a; ), would work. But I dont think so.
We're aware of these possibilities (AMD64 has 64 bit internal FPU accuracy, i386 80 bit).

We (me and greenail) already tested several different configurations and options like -mfpmath=387 to generate 387 fpu instructions on amd64 (which by default uses SSE) and -ffloat-store to write and read back floats to memory after each operation. Every combination we tried had sync errors.

The last solution you give there^^ wouldn't work either because the compiler (with optimisations) would probably generate exactly the same code for both cases.
memarko wrote:Another solution is:

For each operation we have to write function. This can be made in easy way by making it with aritmetric-logic operations. If it is too much floating point operations for this synchronisation, processor will not be able to do so much work because it wont use floating point unit. How much is too much? It depends of the percent synchronisational dependent floating point operation in the whole game and CPU ussage.
What do you mean exactly?

Note that this doesn't have to be super difficult because you can make a CFloat classs and overload all operators +-/* etc.

Same applies for fixed point (about the class).
memarko wrote: b)Problem may be 32 bit or 64 bit floating point fomat.
This can checked with Ansi C function sizeof(name of the type).
I don't know about windows 64 bit, but gcc 64 bit has same size for float and double types. I doubt this is different on windows.
memarko wrote:I dont know much about the concept of the game. So I can be wrong about the solutions.
Thanks for your help anyway
FrantzX wrote:We could just choose a precision to our floats (ie number of zeros after the demical point) as use intergal numbers.

example
1.86f / 3.45f = 0.53913043478260869565217391304348
18600 / 34500 =53.913043478260869565217391304348 --> 54
That's called fixed point arithmetic.

It is a serious solution but we need to carefully research the necessary range and precision, because in general, both are much smaller for fixed point numbers than for floating point numbers. (overflows and underflows are a serious problem for fixed point arithmetic)
Aschmo
Posts: 2
Joined: 27 Jan 2006, 17:09

Post by Aschmo »

[quote=Tobi] (overflows and underflows are a serious problem for fixed point arithmetic)[/quote]

plus you can get weird effects due to truncation. I think strafejump in quake was caused by this.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

And it's slower (forgot that in my first post).

(Last time I tried fixed point was on my old 800Mhz amd duron box. Fixed point was slower than floating point.)
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

To insure cross-platform consistancy with floatpoint operations you must make sure the floatpoint control word is the same on all machines. this controls basicly everything about how the floatpoint engine in the CPU operates and is a part of the IEEE spec on floatpoint handling(well mostly)

The default value depends on what compiler, so you must set it your self to some value.

Keep the floatpoint values in the same data type. single -> double -> single conversions will lose information which is machine dependant on how it happens due to minor rounding errors. Dont to it.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

To insure cross-platform consistancy with floatpoint operations you must make sure the floatpoint control word is the same on all machines. this controls basicly everything about how the floatpoint engine in the CPU operates and is a part of the IEEE spec on floatpoint handling(well mostly)

The default value depends on what compiler, so you must set it your self to some value.
I think spring already sets it, but maybe it was platform dependent or something. I'll take a better look later.
Keep the floatpoint values in the same data type. single -> double -> single conversions will lose information which is machine dependant on how it happens due to minor rounding errors. Dont to it.
This may be the cause of the game going out of sync in M/E long before anything else. I may do a test with all doubles in M/E code replaced by floats...
User avatar
robed
Posts: 56
Joined: 02 Mar 2006, 03:18

Post by robed »

Here's an idea, although it may not be the best. Why not let the clients just simply be a 'close enough' simulator. Have the server be the authority and send out "key frames" which basically resync the clients, every say, 100 game ticks. Now what will happend is sync errors all the time, with a resync every x ticks, the server being the final authority and being the true simulator. That said, the added bandwidth, and the fact that the server's compiler/CPU will determine accuracy are the downside. Upside, you don't have to look for sync errors, you expect them, so you simply know to always grab whatever the sever sends every x game ticks. Also don't have to worry about what OS/compiler/options were specified, simply compile and play.

Dono how much change this sort of thing would require, but I'm assuming you could use code in unsynced data to transmit the data stored in synced. Just a thought ;p
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

We have been thinking about this, but IIRC we came to the conclusion that a full resync takes to much bandwidth. Something like continuously resyncing the units going out of sync might be a solution tho, and if it works, I think it is the perfect solution.
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

Tobi wrote:Something like continuously resyncing the units going out of sync might be a solution tho, and if it works, I think it is the perfect solution.
You will have to.

Given 2 floatpoint values (float a,b), and preforming arbitary operations on them every frame in a consistant and repeating pattern, the final value at any given time will not the same on 2 differemt machines due to machine dependant rounding of the lowend bits.

You must have some form of resync frames
Post Reply

Return to “Engine”