Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#/XNA - Multiplication faster than Division?

I saw a tweet recently that confused me (this was posted by an XNA coder, in the context of writing an XNA game):

Microoptimization tip of the day: when possible, use multiplication instead of division in high frequency areas. It's a few cycles faster.

I was quite surprised, because I always thought compilers where pretty smart (for example, using bit-shifting), and recently read a post by Shawn Hargreaves saying much the same thing. I wondered how much truth there was in this, since there are lots of calculations in my game.

I inquired, hoping for a sample, however the original poster was unable to give one. He did, however, say this:

Not necessarily when it's something like "center = width / 2". And I've already determined "yes, it's worth it". :)

So, I'm curious...

Can anyone give an example of some code where you can change a division to a multiplication and get a performance gain, where the C# compiler wasn't able to do the same thing itself.

like image 442
Danny Tuppeny Avatar asked Feb 19 '11 22:02

Danny Tuppeny


1 Answers

Most compilers can do a reasonable job of optimizing when you give them a chance. For example, if you're dividing by a constant, chances are pretty good that the compiler can/will optimize that so it's done about as quickly as anything you can reasonably substitute for it.

When, however, you have two values that aren't known ahead of time, and you need to divide one by the other to get the answer, if there was much way for the compiler to do much with it, it would -- and for that matter, if there was much room for the compiler to optimize it much, the CPU would do it so the compiler didn't have to.

Edit: Your best bet for something like that (that's reasonably realistic) would probably be something like:

double scale_factor = get_input();

for (i=0; i<values.size(); i++)
    values[i] /= scale_factor;

This is relatively easy to convert to something like:

scale_factor = 1.0 / scale_factor;

for (i=0; i<values.size(); i++)
    values[i] *= scale_factor;

I can't really guarantee much one way or the other about a particular compiler doing that. It's basically a combination of strength reduction and loop hoisting. There are certainly optimizers that know how to do both, but what I've seen of the C# compiler suggests that it may not (but I never tested anything exactly like this, and the testing I did was a few versions back...)

like image 58
Jerry Coffin Avatar answered Oct 07 '22 00:10

Jerry Coffin