Page 42 - Developer
P. 42
INNER PRODUCT // bRUCE DawsON
further reading
This article is based on a series of thirteen13 blog posts written
this year. To read more details, explanations, and code, and
to discuss this article visit http://randomascii.wordpress.
com/2012/09/09/game-developer-magazine-floating-point.
Years ago, I wrote an article on comparing floating-point
numbers that became unexpectedly popular despite its numerous
flaws. As an act of penance for its imperfect advice, I recently
wrote a series of blog posts discussing floating-point math, most
of which have been summarized in this article. You can find more
of my work on floating-point math here; www.altdevblogaday.com/
author/bruce-dawson/. Also, no floating-point article would be
complete without a reference to David Goldberg’s classic article
“What Every Computer Scientist Should Know About Floating-Point
Arithmetic” (http://docs.oracle.com/cd/E19957-01/806-3568/
Figure 4: testing the Visual studio debugger for floating-point bugs. ncg_goldberg.html). It was written in a time when the IEEE floating-
point math standard was not yet universal, but it still contains
whether this works when you can float f1 = 1023.99328f; important insights.
test it in the time it takes to get a float f2 = 1023.993347;
cup of coffee.
While the standard requires In versions of Visual Studio prior point unit, there is no cost to this want the calculation evaluated using
that floats printed with nine digits to VS 2012, these two numbers higher intermediate precision, double precision, and the compiler
of mantissa will round-trip, this is will both be displayed with eight but when using SSE/SSE2 these will dutifully add in three conversion
not quite guaranteed if you print significant digits, as 1023.9933. higher-precision intermediates are operations.
floats with one implementation And yet, these two floats are a problem. Each input float has to The fix in this case is trivial—just
and then scan them from text in actually distinct floats with be explicitly converted to double add a trailing “f” to the floating-
another (say, VC++ and gcc). If this different values. Figure 4 shows precision, using cvtps2pd. If the point constant. The trick is realizing
is critical for your needs, you may this issue at work in an earlier result is stored in a float then it will when you have forgotten to do this.
need to test this. version of Visual Studio (top), have to be converted from double You could scan your source code
though I am happy to note that I using cvtpd2ps. The conversion for double-precision constants, or
Lies, damned Lies, and reported it to Microsoft and it has instructions all have similar latency look in the assembly language for
debuggers since been fixed in Visual Studio to a floating-point add or multiply. conversation instructions. Neither
» The corollary of the above point 2012 (bottom). All these conversions can add a technique can easily distinguish
is that your debugger’s watch noticeable cost—I’ve seen more between performance-critical code,
and code where the conversions
The simple fix to the timing problem is to store time in a 64- are harmless, but they are the
bit number—either a double or a 64-bit integer (representing the best options I have to offer. If you
elapsed count of microseconds or nanoseconds). These techniques find excessive conversions, check
both work, but they are not intrinsically safe because it is very likely your compiler settings and your
that, even though your GetGameTime() function returns a double, input values.
some junior programmer will store the result in a float and you’re
back to having bugs that only occur after hours of gameplay. Let’s end this article with a haiku:
Floating point game math
window (and memory window, Precision and PerFormance than 40% overhead from them. Is very fast and useful
tooltips, registers window, etc.) PitFaLLs Luckily when you compile with / But not accurate
needs to display floats with at » All the modern CPUs I’m familiar fp:fast, or for 64-bit, or using VS
least nine digits of precision. with will perform float or double- 2012, the compiler does not insist on bruce dawson first worked
Otherwise two floats that print precision math at the same speed. using double-precision temporaries. professionally on games in 1987 at
to the same text value might And yet, double-precision math can However you can still inadvertently Distinctive Software Inc., where the
actually be different floats— have significant performance costs trigger this performance-harming coding standard mandated ‘“colour’”
leading to obvious confusion. that are often hard to see. behavior, with benign-looking code spelling and ‘“zed-buffer’” pronounciation.
Visual Studio’s debugger has If we ask the compiler to like this: He has left the game industry twice, but
for many years only printed add some floats together, it may always returns. Most recently he worked
numbers with eight digits of decide, for complicated reasons, f1 = f2 + 0.5 * f3; in the Xbox group at Microsoft for six
precision. (Oops.) To test this in to do the calculation at double years, then on Microsoft Windows, and is
your debugger of choice, create precision. This is the default on Although f1, f2, and f3 are floats, “0.5” now a developer at Valve.
a program containing these Visual Studio 2010 and earlier is not. By including a double-precision
statements and view the value of when compiling 32-bit code. constant in this calculation, you are His parents did finally forgive him for
these variables: When using the x87 floating- explicitly telling the compiler that you dropping out of university.
40 gamE DEvElOPER | OCTObER 2012