I have a few of simple guidlines I use to make this decision .. and it has NOTHING to do with optimization of the compiler.
If the partial expression is more than 1 or 2 elements in size I think to see if I can find a good name that embodies what the value of the partial expression is .. if so, I use the partial expression version, with the good name ... which gives the added bonus of documenting it right in the code, for me in the future.
If the partial expression is KNOWN to be costly to calculate, then I do the operation once and store it in a temporary variable (I would not repletadly translate a matrix the exact same way 4 times in a row .. I'd do it once). I STILL spend at least 30 seconds trying to think of a decent name for the beast - just makes life easier.
If the partial expression is not particular complex to write, does not have a good name to embody its meaning, and isn't known to be costly to do ... I STILL refactor it out of my code most of the time, if it just makes the subsequent 4 lines of code even slightly easier to read. And also for the simple sake of the DRY principle ... (Don't Repeat Yourself) ... repeating yourself opens up too much maintenence work, and too much room for error.
Is this sort of 'optimization' necessary?
Quote:Original post by mattnewportThe only hint I'm aware of for VC++ otpimization is __assumeQuote:Original post by Fruny
GCC lets you tag a function with the pure attribute, telling the compiler that the function has no side-effects and that the return value depends only on globals and function parameters. You can go one step further and add the const attribute (which isn't the same thing as using the const keyword in a normal C or C++ sense), which tell the compiler that the function doesn't rely on global memory at all (that includes not dereferencing pointers passed as parameters either). Both allow the compiler to perform common subexpression elimination on the function call.
I was thinking something exactly like the const attribute would be really useful in VC++ only the other day. Interesting to know that it exists for GCC. You don't know if there's anything equivalent for VC++ (2005) do you?
It works much like assert - you pass it a condition, but the difference is that assert closes the program when the condition is false, while __assume tells the compiler it doesn't have to consider the false case (so you enter the realm of undefined behavior if the condition is false).
I'm not sure how usefull it is, but it seems like it'd be a good idea to have an assert macro that does assert in debug mode and __assume in release mode just so the compiler can take advantage of the stuff you've tested already.
Unless this is code being run in a tight loop or some other part of the code that runs very often, that sort of optimization just really isn't necessary. Are you really going to notice a nanosecond or two? Clarity is more important in my opinion. But definately consider the situation to see if it's necessary.
Quote:Original post by helix
Unless this is code being run in a tight loop or some other part of the code that runs very often, that sort of optimization just really isn't necessary. Are you really going to notice a nanosecond or two?
In his example, there's a sqrt, a pow, and an abs. The abs requires a branch, and with intrinsics disabled the sqrt and pow are going to be a table lookup at the very least (with a potential cache miss). Important during loading time? Probably not. But certainly something to keep an eye out for, especially if it's possible to need the code in even a reasonably fast loop. You lose nothing by arranging it intelligently to begin with.
This is an example of times that you should be conscious of what you're doing beforehand. Will it matter to do this sort of thing 1, 2, or 10 times in your code? Probably not. But slowly, as hundreds of micro-anti-optimizations from across your project start to pile up, things will grind to a halt for no apparent reason.
The compiler should optomize that type of thing, but the more important issue is readability. However, since in this case its both optomized and readable, then thats the ideal way to go. Just make sure you pick a good name for that variable.
sqrt, pow, & abs can be quite slow, so a partial calc is not unreasonable.
This code needs inline functions though, the partial calc should probably be a parameter to an overloaded operator.
This code needs inline functions though, the partial calc should probably be a parameter to an overloaded operator.
Quote:Original post by Polymorphic OOPThat about sums it up.
Whether it's more optimized or not you should store the result and reuse it anyway. Don't embrace code redundancy! Let's weigh the benefits of each:
The one with the partial calculation makes the complex calculation only appear once in code to the person looking at it. One simple identifier is used in the following expressions making it easy to see that it's the same value used. Both a programmer and a compiler can much more easily see that you only need to do those calculations and call that function only once, using the return for all of the remaining calculations. You can give that intermediate calculation a name that identifies what it represents in the following expressions, making it more clear as to what you are doing. You have one more line of written code, but you have much less operations. If you wish to change how the calculation is performed, you only have to change it once for the entire group of statements as opposed to once for each line. Finally, it's possible that the code will be more optimized, since in order to make that optimization the compiler would have to know that the functions you are calling produce the same result every time for the same values.
Now, what exactly do you think you benefit from showing the redundant calculation in code? Sure, you have one less line of code, but you have a lot more operations; most of which are redundant. It is less obvious to a reader or a compiler that the calculation has the same result in each expression. The expression is harder to read. It's possibly less optimized, and finally, it's harder to maintain.
Go with storing the partial calculation.
It's the same thing as how you should use const's instead of the same number in lots of places. A calculation should be treated no differently.
I've honestly worked on a project where someone duplicated things so much that the project actually had 5 source files that were quite long and differed by only a couple of lines. Not to mention that they managed to write things like an byte to hex-string routine that was almost 100 lines long thanks to a seperate case for each digit, in each place. Don't you just love fixing the same bug 5 times?[sick]
If you don't refactor to remove redundancy you'll often miss the big picture.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement