Skip to main content
GameDev.net gamedev.net
🔒 Locked

Double or Float

Started by Snatch Jun 21, 2004 at 11:22 AM 28 replies 5k views
Original Post
Snatch
Snatch
I am writing a little game engine and i was wondering if the 3D part should use double or float to manage all number. I have incorporated Lua language in my engine and all numbers are double, is this a performance killer ?
OrthoDiablo
OrthoDiablo
Choosing double over float depends on the maximum size of the world you are going to have. If the extra precision you get with the double is important to you, then use double, overwise floats should be okay.
Give a man a fish and you feed him for a day; teach him to use the Net and he won't bother you for weeks.
VBBR
VBBR
The majority of 3D apps use floats (I think).
So you'll create an MMORPG, uh? Well, what about reading THIS?
fyhuang
fyhuang
Double will take up more space, but I don't think it should be any kind of a 'performance killer'... unless I'm wrong, there should be barely any difference between doing arithmetic on floats and doing arithmetic on doubles.
- fyhuang [ site ]
pan narrans
pan narrans
You should be fine with floats unless you need really good precision. And if you plan on having a huge game world then you might want to think about a way of resetting the origin occasionally so that the distances don't start to lose precision. I've heard that in preliminary tests of the Dungeon Seige engine there were parts of the world that continuously shook as the floating-point precision was so bad when you moved really far from the origin. That shouldn't be a big worry for you.
Minister of Propaganda : leighstringer.com : Nobody likes the man who brings bad news - Sophocles (496 BC - 406 BC), Antigone
Goldfish
Goldfish
Quote:
Original post by fyhuang
Double will take up more space, but I don't think it should be any kind of a 'performance killer'... unless I'm wrong, there should be barely any difference between doing arithmetic on floats and doing arithmetic on doubles.


I made a fractal generator some time ago, and experimented with using both floats and doubles. I don't remember the exact numbers, but the speed of my generator function greatly increased when switching to floats. The algorithm used some real heavy arithmetics, though, so I don't know how much difference using float over double will make in other programming topics like engines.

Floats will do good in most situations.
2 + 2 = 5 for extremely large values of 2
Matei
Matei
In fact, the 80x86 architecture (i.e. Intel Pentium, AMD, etc) does all floating-point calculations using doubles (or maybe an even larger 80-bit type.. I don't remember exactly). So if you are doing calculations purely on the CPU, it shouldn't matter much. However, there are several issues that could make double slower, especially in a game:
- Doubles take more time to move around because they take up twice the space; this is important only if you have large numbers of numbers you need to calculate with of course... For example with polygonal meshes, or something like sound processing (?).
- If you're really unlucky and using *lots* of numbers, then you might run out of cache space with doubles whereas all the numbers would've fit in cache if they were floats.
- There are special SIMD instructions that can make independent calculations faster if you use floats, by "packing" them into groups of 4 (?) and then operating on these.
- If you're using library functions that are defined to take floats, it's not a good idea to keep converting doubles to floats and vice versa whenever you call the function.
- Graphics cards use floats internally, so if you're doing graphics using DirectX/OpenGL, everything will have to be converted to float anyway, and it's better to have it as float in the first place than to keep converting over and over every frame.

Since you're likely not doing your graphics or any heavy physics in Lua, it might not matter whether you use doubles or floats there.
Thunder_Hawk
Thunder_Hawk
typedef real float;


If you place that in a global header file somewhere and stick to always using a real, you'll always have the option of switching to a double if you need to without too much fuss (replace float with double and recompile your project).
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Forma
Palidine
Palidine
Quote:
Original post by Thunder_Hawk
typedef real float;


If you place that in a global header file somewhere and stick to always using a real, you'll always have the option of switching to a double if you need to without too much fuss (replace float with double and recompile your project).



It's a really good idea to do that with most of your data types anyway. I had several iterations of nightmare when i needed to increase from unsigned char -> unsigned int in my data formats. i eventually moved to a localized typdef system so when the whim took me to change things in a particular area it was really easy instead of a 4 hour process of tracking down every last static_cast.


-me
fyhuang
fyhuang
Yes, why I thought that there shouldn't be a speed difference is because the math co-processor does math with integers, and I believe 80-bit floats. 64-bit floats are supported, if my memory is correct. IMHO, the coprocessor shouldn't be doing all that much more work with the 80-bits than with the 64-bits, and besides, just like the CPU works better with 32-bit variables than with 16-bits, the coprocessor might work better with 80-bit floats. Just a thought.
- fyhuang [ site ]
CoffeeMug
CoffeeMug
Hmmm, I remember reading that on x86 platform changing "float" to "double" in a C++ compiler makes absolutely no different (i.e. your source compiles to the same code).
fyhuang
fyhuang
Changing the floats to doubles will affect the memory usage, but by very little.
- fyhuang [ site ]
Yann L
Yann L
Quote:
Original post by CoffeeMug
Hmmm, I remember reading that on x86 platform changing "float" to "double" in a C++ compiler makes absolutely no different (i.e. your source compiles to the same code).

On x86 platforms, float and double are two different types, take different amount of memory, are treated differently by the FPU, need to push a different amount of data on the stack for function arguments, etc. The generated code will therefore be very different.

Quote:

Changing the floats to doubles will affect the memory usage, but by very little.

It will double the required memory: float = 4 bytes, double = 8 bytes. Doubling memory usage is not exactly what I would consider "very little". But it depends on how much data you keep in floating point format, of course.
CoffeeMug
CoffeeMug
Quote:
Original post by Yann L
Quote:
Original post by CoffeeMug
Hmmm, I remember reading that on x86 platform changing "float" to "double" in a C++ compiler makes absolutely no different (i.e. your source compiles to the same code).

On x86 platforms, float and double are two different types, take different amount of memory, are treated differently by the FPU, need to push a different amount of data on the stack for function arguments, etc. The generated code will therefore be very different.

I remember reading Inner Loops a few years ago in order to hand optimize my Perlin Noise routines when I ran into this issue. My memory is very vague, I'll have to double check this when I get home, but I'm pretty sure it was related to double not giving more precision than float on x86. Again, I don't want to give out incorrect information, so I'll have to double check that.
Yann L
Yann L
Quote:
Original post by CoffeeMug
Quote:
Original post by Yann L
Quote:
Original post by CoffeeMug
Hmmm, I remember reading that on x86 platform changing "float" to "double" in a C++ compiler makes absolutely no different (i.e. your source compiles to the same code).

On x86 platforms, float and double are two different types, take different amount of memory, are treated differently by the FPU, need to push a different amount of data on the stack for function arguments, etc. The generated code will therefore be very different.

I remember reading Inner Loops a few years ago in order to hand optimize my Perlin Noise routines when I ran into this issue. My memory is very vague, I'll have to double check this when I get home, but I'm pretty sure it was related to double not giving more precision than float on x86. Again, I don't want to give out incorrect information, so I'll have to double check that.

Hmm, I have Inner Loops, but it's been a while that I read it.

Normally, on x86 platforms, all calculations are internally carried out at 80 bit precision, and are stored as either 64 bit or 32 bit later. Unless you specifically tell the FPU to compute everything at 64 or even 32 bit internal precision, which can (used to) speed up things like division, multiplication, square roots, etc.
fyhuang
fyhuang
In general terms, yes, doubling memory is not considered very little, but if you look at the big picture, for your average game, you aren't going to have millions of real numbers :). For math/simulation applications that require lots of number-crunching, it probably will make a difference, but most games don't need that many numbers. Memory is also at a premium these days (with the exception of if the user uses XP :) ). Most likely the amount of numbers your game uses isn't going to exceed maybe 1/2 a MB.
- fyhuang [ site ]
Charles B
Charles B
None mentionned the big issue : DATA ALIGNMENT.

A lot of care must be taken so that doubles are aligned on 64 bits boundaries, else the FPU will stall very poorly. It's not always just as simple as setting a few compiler options. In details it can be quite subtle. Anyway, aligning the stack costs more instructions for the compiler, such as and esp, -8 or and ebp, -8, which adds latency and AGIs.

Else it's true that double and float operations have exactly the same timings since the first Pentium. Apart alignement, memory consumption and thus L1 cache can be a significant issue worth to consider.

Conclusion : Use float, unless you really need more precision. Then care about data alignement. Last, it's already been mentionned, code based on SIMD will also favor floats.

EDIT : about precision.

Yann L is right. It depends on the FPU control flags. Functions exist in the C libraries, no need for asm. One has to be careful in multithreaded environments. Note that this precision only affects the speed of complex flops, such as division or sqrt. But muls or adds always cost the same.

Precision has nothing to do directly with the floats or doubles ... when in registers. But once the float data is stored in memory, of course many least significant bits are potentially lost.
"Coding math tricks in asm is more fun than Java"
RenderTarget
RenderTarget
I'm not 100% sure, but is there not a stall associated with switching between doubles and floats at runtime? This could bit you if you're using OGL or DirectX, as they use floats natively.
[sub]My spoon is too big.[/sub]
BitBlt
BitBlt
Considering memory bottlenecks are much more of an issue than CPU speed, I'd stick with floats until doubles are absolutely necessary, since doubles would do just that to your memory, double it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.