Aussie AI
Reciprocal Multiplication
-
Book Excerpt from "Generative AI in C++"
-
by David Spuler, Ph.D.
Reciprocal Multiplication
Division is a slow operation, whether in a CPU or a GPU. Multiplication is often significantly faster than division, and in some cases a division can be replaced by a multiplication using the reciprocal. A case in point is floating-point division by a constant. For example, consider the division:
f = g / 100.0;
This can be replaced by the multiplication:
f = g * 0.01; // Reciprocal
If the divisor is a symbolic constant, it is possible to replace the symbolic constant with a hard-coded constant (or another symbolic constant). However, it is more convenient to replace the constant with an explicit reciprocal calculation. For example, consider the code:
f = g / DIVISOR;
This can be rewritten as:
f = g * (1.0 / DIVISOR);
The compiler should calculate the reciprocal using “constant folding” at compile-time. Note that the brackets around the division expression are probably not strictly necessary because optimizers know about associativity, but are certainly helpful to make life easier for the optimizer (and these poor critters need a break every now and then).
If the divisor is a complex expression, the compiler might not automate the use of a reciprocal. Here's the slow version of division by a scale factor:
v[i] /= sqrtf(3.14159f);
Here's the faster way using the reciprocal of the constant:
v[i] *= 1.0f / sqrtf(3.14159f);
And we really should pre-calculate this constant using constant folding and a static
variable:
static const float scalefactor = 1.0f / sqrtf(3.14159f); v[i] *= scalefactor;
• Next: • Up: Table of Contents |
The new AI programming book by Aussie AI co-founders:
Get your copy from Amazon: Generative AI in C++ |