tags:

views:

723

answers:

8

Which is fastest way to implement a operation that returns the absolute value of a number?

x=root(x²)

or

if !isPositive(x): x=x*(-1)

Actually this question can be translated as, how fast is a if(and why please).

My college programing professors always told me to avoid if's for they are extremly slow, but I always forgot to ask how slow and why. Does anybody here knows?

+14  A: 

Ugh, your teachers actually told you that? The rule most people follow is to make your code readable first, and then tweak any performance problems after they are proven to actually be problems. 99.999% of the time you are never going to see a performance problem because you used one too many if statements. Knuth said it best, "premature optimization is the root of all evil".

Ed Swangren
Knuth may have said that but he wasn't the first. Check out your link, it's thought it was originally (Sir) Tony Hoare. As even Knuth would admit: "If I have seen so far, it's because I've stood on the shoulders of giants". Not one of his, but I'm sure he'd agree.
paxdiablo
I understand your point, but it has nothing to do with my question
Diones
Pax: Knuth *did* say it first. He just mistakenly attributed it to Hoare 15 years later. See http://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/
ShreevatsaR
I stand corrected.
paxdiablo
++ I was a professor, so I can attest that professors can say anything, because who's going to call their bluff? They're like clerics in that regard. Professors have more of an investment in getting through the semester than in passing on good information.
Mike Dunlavey
... correction: "some" professors.
Mike Dunlavey
@Diones: Yes it does, you are just intent on finding the answer you *think* that you need.
Ed Swangren
@Ed Swangren: I should have stated in my question that I already heard Knuth's statement about premature optimization and that I was looking for the answer, out of sheer curiosity.
Diones
Well, then why didn't you just time it yourself?
Ed Swangren
+1  A: 

The modulo operation is used to find a remainder, you mean absolute value. I modified the question because it should be if !pos(x) then x = x*-1. (not was missing)

I wouldn't worry about the efficiency of an if statement. Instead focus on the readability of your code. If you identify that there is an efficiency problem, then focus on profiling your code to find real bottlenecks.

If you want to keep an eye out for efficiency while you code, you should only worry about the big-O complexity of your algorithms.

If statements are very efficient, it evaluates whatever expression and then simply changes the program counter based on that condition. The program counter stores the address of the next instruction to be executed.

Mulitplication by -1 and checking if a value is greater than 0 both can be reduced to a single assembly instruction.

Finding the root of a number and squaring that number first is definitely more operations than the if with a negation.

Brian R. Bondy
I'm guessing the professor is thinking of If statements stuffing up the pipeline. Which I'm pretty sure doesn't happen in modern processors any more.
Ray
That professor is an idiot - calls to a root() function would also stuff up the pipeline.
paxdiablo
+14  A: 

First off, this is calculating absolute value, not modulus.

Conditionals are slower than plain arithmetic operations, but much, much faster than something as silly as calculating the square root.

Rules of thumb from my assembly days:

  • Integer or bitwise op: 1 cycle
  • Floating-point add/sub/mul: 4 cycles
  • Floating-point div: ~30 cycles
  • Floating-point exponentiation: ~200 cycles
  • Floating-point sqrt: ~60 cycles depending on implementation
  • Conditional branch: avg. 10 cycles, better if well-predicted, much worse if mispredicted
kquinn
+2  A: 

For a start, that's an absolute-value operator, not modulus.

Secondly, IF is blindingly fast since it normally translates to a conditional jump instruction at the machine code level (following the evaluation of the expression, which may be complex, but not in this case since it's a simple check for less than 0). Taking the square root of a number is likely to be much slower (Newton's method would use many, many, IFs at the machine level).

paxdiablo
+3  A: 

At first, it is a absolute value calculation, not a modulus. Calculating the square root is probably one of the worst things you could do accept a smart compiler optimizes it away because it is really slow.

Usually there is a library function for doing this; something like Math.Abs(). Multiplying with -1 is also unnessesar; just return -x. So a good solution would be the following.

(x >= 0) ? x : -x

The compiler will probably optimize this to a single instructions. Ifs may be quite expensive on moden processors because of the long execution pipelines. Their calculations must be thrown away if a branch was misspredicted and the processor started executing the instructions from the wrong code path. But because of the mentioned compiler optimization you need not care in this case.

Daniel Brückner
+1  A: 

The time taken to do a square root is much greater than the time taken to do an conditional. If you have been taught to avoid conditionals because they are slow, then you have been misinformed. They are a good deal slower than trivial operations like adding or subtracting integers or bit shifting - which is why unrolling loops can be of benefit only if you are doing such trivial operations. But in the grand scheme of things conditionals are good and fast, not bad and slow. To do something as complicated as call a function or calculate a square root to avoid a conditional statement is crazy.

Also, instead of (x = x * -1) why not do (x = 0 - x)? Maybe the compiler will optimize them the same, but isn't the second one simpler anyway?

thomasrutter
"Also, instead of (x = x * -1) why not do (x = 0 - x)? Maybe the compiler will optimize them the same, but isn't the second one simpler anyway?"Sure it is I just never thought like that...
Diones
+1  A: 

Are you using 8086 assembly? ;-)

                ; abs value of AX
   cwd          ; replicate the high bit into DX
   xor  ax, dx  ; take 1's complement if negative; no change if positive
   sub  ax, dx  ; AX is 2's complement if it was negative The standard
                : absolute value method works on any register but is much
                ; slower:

   or   bx, bx  ; see if number is negative
   jge  notneg  ; if it is negative...
   neg  bx      ; ...make it positive
notneg:         ; jump to here if positive

(flagrantly stolen)

Mark Maxham
+2  A: 

There is a great trick to calculate the absolute value of a 2s-complement integer without using an if statement. The theory goes, if the value is negative you want to toggle the bits and add one, otherwise you want to pass the bits through as is. A XOR 1 happens to toggle A and A XOR 0 happens to leave A intact. So you want do something like this:

  uint32_t temp = value >> 31;     // make a mask of the sign bit
  value ^= temp;                   // toggle the bits if value is negative
  value += temp & 1;               // add one if value was negative

In principle, you can do it in as few as three assembly instructions (without a branch). And you'd like to think that the abs() function that you get with math.h does it optimally.

No branches == better performance. Contrary to @paxdiablo's response above, this really matters in deep pipelines where the more branches you have in your code, the more likely you are to have your branch predictor get it wrong and have to roll-back, etc. If you avoid branching where possible, things will keep moving along at full throttle in your core :).

vicatcu
+1 This directly answers the question.
mdma