Physics engine: use double or single precision?
Asked Answered
L

5

10

I am making a rigid body physics engine from scratch (for educational purposes), and I'm wondering if I should choose single or double precision floats for it.

I will be using OpenGL to visualize it and the glm library to calculate stuff internally in the engine as well as for the visualization. The convention seems to be to use floats for OpenGL pretty much everywhere and glm::vec3 and glm::vec4 seem to be using float internally. I also noticed that there is glm::dvec3 and glm::dvec4 though but nobody seems to be using it. How do I decide which on to use? double seems to make sense as it has more precision and pretty much the same performance on today's hardware (as far as I know), but everything else seems to use float except for some of GLu's functions and some of GLFW's.

Lama answered 6/12, 2013 at 19:27 Comment(12)
My intuition says float is enough if you do it right. Looking forward to an actual answer :)Quarters
You're overthinking this...Namangan
you could use templates...Guerrero
@KarolisJuodelė: Overthinking? I want to stay consistent and avoid the mess which is lots of mixed stuff and casts everywhere.Lama
A double has enough precision that if you're measuring the distance of the Earth to the Sun, it can still distinguish a difference of a milimeter. Might be excessive.Ferrer
People do not use double-precision in OpenGL often because the majority of GPUs do not support double-precision. The API offers double-precision functions but more often than not the values are truncated to accommodate the single-precision hardware. New GPUs support double-precision shading, but quite a few important operations in the pipeline (texture lookups, for instance) are still limited to single-precision.Addressograph
Even on hardware where double-precision is supported, it requires twice the memory bandwidth to communicate double-precision vertices and many more clock cycles to issue double-precision instructions. Since single-precision is usually adequate, double-precision is useful mostly for GPGPU applications and not so much rendering.Addressograph
@AndonM.Coleman: This isn't just purely rendering though, there are some physics calculations.Lama
Would it be feasible to use double for the physics, and float for the rendering?Grison
typedef float real; Run a profiler with real as a float and real as a double and you'll see the difference.Disbranch
The signatures of the two differ only by a single character in the name and if they take float or double. Write a macro that writes a template perfect forwarding function that statically examines its arguments, determines if they are double esque or float esque, then forwards them to MYNAME ## d or ## f depending. Invoke that macro in a header for each gl function you are using: basically write C++ style overloads, without having to do more than mention the common function name. Alternatively, use the TCHAR pattern. Then test both.Albanese
Use double if you want to use your physics engines on worlds larger than a kilometer or so.Axolotl
F
10

This is all going to depend on your application. You pretty much already understand the tradeoffs between the two:

Single-precision

  • Less accurate
  • Faster computations even on todays hardware. Take up less memory and operations are faster. Get more out of cache optimizations, etc.

Double-precision

  • More accurate
  • Slower computations.

Typically in graphics applications the precision for floats is plenty given the number of pixels on the screen and scaling of the scene. In scientific settings or smaller scale simulation you may need the extra precision. It also may depend on your hardware. For instance, I coded a physically based simulation for rigid bodies on a netbook and switching to float gained on average 10-15 FPS which almost doubled the FPS at that point in my implementation.

My recommendation is that if this is an educational activity use floats and target the graphics application. If you find in your studies and timing and personal experience you need double-precision then head in that direction.

Fargone answered 6/12, 2013 at 19:35 Comment(7)
A solid answer. I would also add that if the OP is familiar enough with templating, he could probably template out the type. For the physics aspect, this should work just fine with either float or double used with no code modificaiton. Sending it to OGL might be a bit more work as you would have to detect if the input type is a float or double and convert accordingly. This could be accomplished with template specialization, though.Dinahdinan
@djechlin it doesn't actually. The OP assumed float and double operations cost the same. Which they dont in terms of memory or cpu time. Also this adds the knowledge of depending on the application.Fargone
It has to be enough to make some kind of playable minigame with, but I guess float will suffice then. So if I get time from glfwGetTime, I should basically immediately cast it from double to float?Lama
You can yea. I wouldn't worry too much about things like GetTime, the bottleneck of your application will likely be collision resolution, drawing, and integration, not timing. Make sure you are consistent with the expensive operations and open GL items.Fargone
I just have a feeling that using float for dt is inaccurate in some way. But I guess it's just some arbitrary thought. But I just realized, I use int pretty much everywhere instead of long, which is similar.Lama
@Lama float is usually fine for delta-T, but depending on your implementation you may want to stay with double for time-points. Otherwise, as time goes on, you're subtracting larger and larger numbers that are only a few tenths or hundreths of a second apart, and eventually your delta-T goes to 0. Of course, this is still a problem with double, but it would take centuries in most cases (depending on how much precision you actually need) before you ran into problems.Centrepiece
@bcrist: All right then. So I'll store time in double and then cast the difference to float and then use float everywhere else.Lama
B
6

Surely the general rule is correctness first and performance second? That means using doubles unless you can convince yourself that you'll get fidelity required using floats.

The thing to look at is the effective size of one bit the coordinate system relative to the smallest size you intend to model.

For example, if you use earth coordinates, 100 degrees works around to around 1E7 metres. An IEEE 754 float has only 23 bits of precision, so that gives a relative precision of only about 1E-7. Hence the coordinate is only accurate to around 1 meter. This may or may not be sufficient for the problem.

I have learnt from experience to always use doubles for the physics and physical modelling calculations, but concede that cannot be a universal requirement.

It does not of course follow that the rendering should be using double; you may well want that as a float.

Bombacaceous answered 10/12, 2013 at 0:20 Comment(0)
H
3

I used typedef in a common header and went with float as my default.

typedef real_t float;

I would not recommend using templates for this because it causes huge design problem as you try to use polymorphic/virtual function.

Why floats does work

The floats worked pretty fine for me for 3 reasons:

First, almost every physical simulation would involve adding some noise to the forces and torques to be realistic. This random noises are usually far larger in magnitude than precision of floats.

Second, having limited precision is actually beneficial on many instances. Consider that almost all of the classical mechanics for rigid body doesn't apply in real world because there is no such thing as perfect rigid body. So when you apply force to less than perfect rigid body you don't gets perfect acceleration to the 7th digit.

Third, many simulations are for short duration so the accumulated errors remain small enough. Using double precision doesn't change this automatically. Creating long running simulations that matches the real world is extremely difficult and would be very specialized project.

When floats don't work

Here are the situation where I had to consider using double.

  1. Latitude and longitudes should be double. Floats simply doesn't have good enough resolution for most purposes for these quantities.
  2. Computing integral of very small quantities over time. For example, Gaussian Markov process is good way to represent random walks in sensor bias. However the values will typically be very small and accumulates. Errors in calculation could be much bigger in floats than doubles.
  3. Specialized simulations that goes beyond usual classical mechanics of linear and rotational motions of rigid body. For example, if you do things with protein molecules, crystal growth, micro-gravity physics etc then you probably want to use double.

When doubles don't work

There are actually times when higher precision in double hurts, although its rare. An example from What every computer scientists should know...: if you have some quantity that is converging to 1 over time. You take its log and do something if result is 0. When using double, you might never get to 1 because rounding might not happen but with floats it might.

Another example: You need to use special code to compare real values. These code often has default rounding to epsilon which for float is fairly reasonable 1E-6 but for double its 1E-15. If you are not careful, this can give lot of surprises.

Performance

Here's another surprise: On modern x86 hardware there is little difference between raw performance of float vs double. The memory alignment, caching etc almost overwhelmingly dominates more than floating point types. On my machine a simple summation test of 100M random numbers with floats took 22 sec and with double it takes 25 sec. So floats are 12% faster indeed but I still think its too low to abandon double just for performance. However if you use SSE instructions or GPUs or embedded/mobile hardware like Arduino then floats would be much more faster and that can most certainly be driving factor.

A Physics engine that does nothing but linear and rotational motions of rigid body can run at 2000Hz on today's desktop-grade hardware on single thread. You can trivially parallelize this to many cores. Lot of simple low end simulations require just 50Hz. At 100Hz things starts to get pretty smooth. If you have things like PID controllers, you might have to go up to 500Hz. But even at that worse-case rate, you can still simulate plenty of objects with good enough desktop.

In summary, don't let performance be your driving factor unless you actually measure it.

What to do

A rule of thumb is to use as much precision as you need to get your code work. For simple physics engine for rigid body, float are often good enough. However you want to be able to change your mind without revamping your code. So the best approach is to use typedef as mentioned at the start and make sure you have your code working for float as well as double. Then measure often and chose the type as your project evolves.

Another vital thing in your case: Keep physics engine religiously separated from rendering system. Output from physics engine could be either double or float and should be typecasted to whatever rendering system needs.

Hausa answered 13/1, 2017 at 9:27 Comment(0)
A
2

Here's the short answer.

Q. Why does OpenGL use float rather than double? 
A. Because most of the time you don't need the precision and doubles 
are twice the size.

Another thing to consider is that you shouldn't use doubles everywhere, just as some things may take require using a double as opposed to a float. For example, if you are drawing a circle by drawing squares by looping through the angles, there can only be so many squares shown on the screen. They will overlap, and in this case, doubles would be pointless. However if you're doing arbitrary floating point arithmetic, you may need the extra precision if you're trying to accurately represent the Mandelbrot series (although that totally depends on your algorithm.)

Either way, in the end, you will need to usually cast back to float if you intend to use those values in drawing.

Ametropia answered 6/12, 2013 at 20:3 Comment(2)
Not to mention up until recently consumer grade GPU hardware didn't even have double-precision capabilities. The ones that do still do not expose double-precision throughout the entire pipeline. So about the only place you benefit from double-precision is for calculations done on the CPU, and that is a pretty unpopular way of implementing physics these days; sure they have CPU fallbacks, but the preferred path is through CUDA, OpenCL or some other GPGPU solution.Addressograph
@Andon Yeah, nowadays people are just making shaders for everything. I've seen some HLSL implementations for mandelbrot but they can only zoom in so far. I think for the most part, everything is still being done on the CPU.Ametropia
S
0

Single prec operations are faster and the data uses less memory less network bandwidth. So you only use double if you gain something in exchange for slower ops and more mem and bandwidth required. There are certainly applications of rigid body physics where the extra precision would be worth it, such as in manipulating lat\lon where single precision only gives you meter accuracy but is this your case?

Since it's educational purpose, maybe you want to educate yourself in the use of high precision physics algorithms where the extra accuracy would matter but lots of rigid body phys involves processes that can only be approximately quantified such as friction between 2 solids, collision reaction after detection etc, that extra precision wont matter you just get more precise approximate behavior :)

Sweven answered 7/12, 2013 at 0:56 Comment(1)
>but lots of rigid body phys involves processes that can only be approximately quantified such as friction between 2 solids this is not true! There are solvers for multibody contacts and if this is too inexact one can retreat to using "the reduced coordinate approach", see book "Game Physic engine development" page 428. The energy based / consrrving principle where you have to do many partial derivatives and calculate a simple looking formula for each special case of constraints. Sadly this is only scratched in the literature and used nowhere?Optime

© 2022 - 2024 — McMap. All rights reserved.