9/17/2008

09-17-08 - 3

Vector dot products and matrix multiplies need to be accumulated in doubles. This is super obvious and I'm sure all the scientific computing people are going "duh" but I bet 99.9% of game engines don't do this. A matrix multiply is just a bunch of dot products, so let's consider the dot product :

dot = ax * bx + ay * by + az * bz;

or

dot = x + y + z;

since all that really matters here is the accumulation. I'm going to assume that this is done like :
dot = x + y;
dot += z;
though the exact order of summation depends on the language convention and compiler and whatnot. The really bad case happens when 'x' is small, 'y' is large, and 'z' is large and nearly exactly negative 'y'. When you compute (x+y) the precision in x is killed, then you add on 'z' and it cancels y, but you get something that's nowhere near where it should be (in a relative sense), eg. (x+y)+z is way off from x+(y+z).

This may seem rather obscure and arcane but in fact it happens all the time in very common cases. When 'a' and 'b' are two vectors that are mostly in the YZ plane (small x component) and are nearly 90 degrees off each other, this is what happens.

Its also super trivial to fix and the performance cost is near zero on platforms where the native float is double anyway like the PC.

I've had so many problems in the last few years with mathematical code failing due to precision, that I now just use doubles everywhere until I see some very good reason to go to floats. Stuff like the SVD and PCA can very easily lead to total garbage if you don't have enough precision in your temporaries. I learn the lessons of coding over and over. Don't prematurely optimize. Always be extra safe and robust until you have a good reason not to be. And check your results even when you're sure you don't have to. I only know that I have had precision problems because I do things like after I get the singular vectors out of the SVD, I go back through and dot them all against each other and assert that they're actually orthogonal to each other.

No comments:

old rants