Archived

This topic is now archived and is closed to further replies.

Values from 0.0 to 1.0

This topic is 5175 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have a need for values in the range 0.0 to 1.0 and I''m stuck on one thing: should I use a float or unsigned char/short? Either would probably work for my purpose (fuzzy logic)... So does anyone have anything ideas?

Share on other sites
easiest to start with float and move to a fixed point representation later on when(if) it becomes neccessary.

Share on other sites
The most logical would be to use float .

However floats are incapable of storing certain values absolutely. Also the soundness of your numerical methods becomes important to prevent accumulation/rounding error being a problem (depending on what you''re doing).

Fixed point numbers are of course also limited in what they can store - however they may make better use of the binary layout for your purposes (e.g. 1.31 fixed point gives you more fractional bits than 1.8.23 IEEE float).

I''d go for float unless you have a reason not to.

Share on other sites
Make it a double instead of a float. No reason not to.

I''m quoting from Lakos here.

Share on other sites
.......

Uhm, there is no way I''m making it a double. I don''t need very high precision with this and I''ve talked to some other people about it. I think I''ll end up using an unsigned short to speed up the math (it will need to be fast because it''s in a game). That is unless I find some easy cool ways to do what I need with floats.

Share on other sites
a lot of floating point math these days is actually faster than integer math. The slow down only occurs when you''re converting between the two.

Share on other sites
quote:
Original post by daerid
a lot of floating point math these days is actually faster than integer math

?!

Share on other sites
quote:
Original post by daerid
a lot of floating point math these days is actually faster than integer math. The slow down only occurs when you''re converting between the two.

O_____________________________________o

/me benchmarks it, brb

Share on other sites
Using the following source code:

#include <stdlib.h>#include <iostream.h>#include <windows.h>int main(){     unsigned int t1, t2, dt, i;     float temp1 = 0;     unsigned int temp2 = 0;     t1 = GetTickCount();     for (i = 0; i < 4200000000; i++)     {          temp1 += .000000001;     }     t2 = GetTickCount();     dt = t2 - t1;     cout << "Floating Point-\n   Total Time: " << dt << "ms\n";     cout << "    Average Time: " << dt / 4200000000.0 << "ms\n\n";     t1 = GetTickCount();     for (i = 0; i < 4200000000; i++)     {          temp2 += 1;     }     t2 = GetTickCount();     dt = t2 - t1;     cout << "Integer-\n    Total Time: " << dt << "ms\n";     cout << "    Average Time: " << dt / 4200000000.0 << "ms\n\n";     system("pause");}

I got the following results:

Floating Point-   Total Time: 5625ms    Average Time: 1.33929e-06msInteger-    Total Time: 5547ms    Average Time: 1.32071e-06ms----------------------------------------------------------Floating Point-   Total Time: 5656ms    Average Time: 1.34667e-06msInteger-    Total Time: 5609ms    Average Time: 1.33548e-06ms----------------------------------------------------------Floating Point-   Total Time: 6000ms    Average Time: 1.42857e-06msInteger-    Total Time: 5609ms    Average Time: 1.33548e-06ms

So as three tests show, with 4.2 billion additions per test, integer addition is faster than floating point addition. I''ll assume this of other operations because my experience with assembly language says I should.

Share on other sites
Notice, though, that the difference isn''t very significant. And if you were to take advantage of SIMD or 3DNow! features...

Share on other sites
1. The range between 0 and 1 requires "fixed point", so a comparison with plain "integer" isn't totally fair anyway since although the majority of the maths can be treated as plain integer, at some point, a scale is usually required - the time taken for that occasional bitshift to move the decimal point should be accounted for.

2. Simple loop tests aren't at all accurate for benchmarking (I cache warmup, process/thread context switches in the middle of your loop etc, D cache warm up for the first access to the timer variables etc)...

3. ...Nor are they reprensentative of what the compiler would generate for a real app. In the real app, if the compiler runs out of integer registers before it does FP stack space, the results would skew in favour of the FP code.

4. The MSVC optimiser collapses those loops anyway, so you only get valid results by disabling optimisations of the loop (say by making the iterator volatile) - which results in some pretty sub-optimal pooey code generation.

5. The float constant you were adding is treated as a double.

6. try the following slightly modified (and fairer) version of your code in both release and debug:
#include <stdlib.h>#include <iostream.h>#include <windows.h>int main(){         unsigned int dt;     unsigned int t1 = GetTickCount();         float temp1 = 0.0f;         for (volatile unsigned int i = 0; i < 4200000000U; ++i)         {                  temp1 += .00013f;         }         unsigned int t2 = GetTickCount();         dt = t2 - t1;         cout << "Floating Point-\n   Total Time: " << dt << "ms\n";         cout << "    Average Time: " << dt / 4200000000.0f << "ms\n\n";         unsigned int t3 = GetTickCount();         unsigned int temp2 = 0U;             for (volatile unsigned int j = 0; j < 4200000000U; ++j)         {                  temp2 += 13;         }             unsigned int t4 = GetTickCount();         dt = t4 - t3;         cout << "Integer-\n    Total Time: " << dt << "ms\n";         cout << "    Average Time: " << dt / 4200000000.0f << "ms\n\n";         return 0;}

6a. On the (Intel CPU) machine I'm browsing on, with a DEBUG build I got the following results for two runs:
Floating Point-   Total Time: 60046ms    Average Time: 1.42967e-005msInteger-    Total Time: 12789ms    Average Time: 3.045e-006ms-------------------------------------Floating Point-   Total Time: 59726ms    Average Time: 1.42205e-005msInteger-    Total Time: 12788ms    Average Time: 3.04476e-006ms

6b. Now let's see the (MSVC6 compiler optimised) RELEASE version on the same machine:
Floating Point-   Total Time: 19287ms    Average Time: 4.59214e-006msInteger-    Total Time: 21601ms    Average Time: 5.1431e-006ms----------------------------------------------Floating Point-   Total Time: 19568ms    Average Time: 4.65905e-006msInteger-    Total Time: 21592ms    Average Time: 5.14095e-006ms

6c. See how much the surrounding code can skew your "benchmarking" results...

7. That's not to say MSVC6's optimisation of FP code is ideal - it's not, it misses many good opportunities to use FP latency hiding and uses temporary flushes to memory too often (though that could be for numerical consistency). The integer optimisation code in MSVC6 is better.

8. And no, I've not got any suggestions as to why the release integer code ends up slower than the debug integer code

[BAH! - edit kills the source tags]

[edited by - S1CA on October 12, 2003 7:05:52 PM]

Share on other sites
Use a typedef, make wrapper classes, decide later.

(So you can just use x==y in code, and implement your Float operator== using an epsilon).

[edited by - Magmai Kai Holmlor on October 12, 2003 9:11:57 PM]

Share on other sites
Well actually, I will not be using floats. You see all those optimizations and stuff you take into account are bogus in something that isn't constantly kepts on the floating point stack (which mine won't be). Oh, and it kinda sounds like you are talking down to me; please don't. I know and have used assembly quite a bit; I've just heard different things aobut this and decided to ask. Anyway, neither of our benchmarks is really fair to using fuzzy logic because you never really have it on the FP stack waiting to be used/etc.

And BTW, it wasn't a double; note how it was a float.

EDIT: Just ran your version on my computer; and integers were actually still faster O____o.

[edited by - Puzzler183 on October 12, 2003 9:30:34 PM]

Share on other sites
quote:

1. The range between 0 and 1 requires "fixed point", so a comparison with plain "integer" isn''t totally fair anyway since although the majority of the maths can be treated as plain integer, at some point, a scale is usually required - the time taken for that occasional bitshift to move the decimal point should be accounted for.

2. Simple loop tests aren''t at all accurate for benchmarking (I cache warmup, process/thread context switches in the middle of your loop etc, D cache warm up for the first access to the timer variables etc)...

3. ...Nor are they reprensentative of what the compiler would generate for a real app. In the real app, if the compiler runs out of integer registers before it does FP stack space, the results would skew in favour of the FP code.

BTW, your test was subject to these as well...

Share on other sites
quote:
And BTW, it wasn''t a double; note how it was a float.

temp1 += .000000001;

Note how you you don''t have an "f" at the end of that constant, THAT was what I was referring to. In response the compiler produces code which fetches a double :

warning C4305: ''+='' : truncation from ''const double'' to ''float''
...

quote:
You see all those optimizations and stuff you take into account are bogus in something that isn''t constantly kepts on the floating point stack (which mine won''t be)

Likewise with integer code that won''t fit into registers!!. My point there being neither is guaranteed to be faster than the other, and simple loop tests are NOT valid for making performance decisions. That was in response to your post saying:

quote:
So as three tests show, with 4.2 billion additions per test, integer addition is faster than floating point addition

quote:
Oh, and it kinda sounds like you are talking down to me; please don''t. I know and have used assembly quite a bit;

I wasn''t. Likewise, but I''ve no interest in getting into a pissing contest.

quote:
I''ve just heard different things aobut this and decided to ask.

Though TBH, your response comes across as if you''ve already made your mind up and don''t want to listen to what anyone else has to suggest...

quote:
Anyway, neither of our benchmarks is really fair to using fuzzy logic because you never really have it on the FP stack waiting to be used/etc.

Exactly. My modification of your benchmark was only to challenge the assertion that your benchmark proves floats were slower than integers. They''re neither slower of faster - it depends on the code where they''re used, and on what the compiler produces.

Share on other sites
frankly, the slowest part for your fuzzy controller is going to be evaluating all the if statements in your rule set anyway [unless your using a complex output generation function]. So considering the ammount of branching youll be doing I wouldnt worry too much about the tiny bits of performance loss from float addition as opposed to int addition.

finally, fuzzy controllers can be executed beautifully in parallel, so in the end, if your really hungry for speed, you would write it all in SSE2 code anyway.

i would be personally quite supprised if you found that your actual fuzzy logic code was making a noticable difference to your game speed.

Share on other sites
(assume arch=Athlon XP) Those benchmarks are silly - of course integer is faster. 3 integer units, latency 1 clock vs. 1 FADD pipe, latency 4 clocks. The loops suck because you''re doing back to back dependent adds (limited by mem access time). You can reach 2 int adds/clock throughput (well, ignoring mem access latency) by unrolling, but only 1 float add/clock.
Things change if using 3DNow!, of course

• Forum Statistics

• Total Topics
628682
• Total Posts
2984213

• 11
• 13
• 13
• 9
• 10