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
   37   38   39   40   41   42   43   44   45   46   47