Converting speed

Hello everybody!
Today...I have a question. I have no idea about the <math> function fabs(). Because, an example may prove :

1
2
3
4
5
6
7
8
double fVal = -95.3886;
double fResult;
//Record time...
for (volatile long i = 0;i < 100000000;i  )//100 million loops
{
//fResult = -fVal; //1.18 sec
//fResult = fabs(fVal); // 5.802 sec !!!!!!
}

From the example above, it seems the fabsf() function is redundant because it performs very slow and without it the basic C code still works very well (lighting speed IMO). Do you know why?
Last edited on
fabsf is not standard as far as I know and I think it only works on float. You use double so it will have to convert between double and float a lot if you use it in your program.

fabs is not the same as negation so it's not strange that fabs is slower.
fabs is not the same as negation so it's not strange that fabs is slower.


This. Your test is unfair. fabs has to actually check to see if the number is negative or not. Conditionals are significantly slower.

Try this instead:

1
2
3
4
5
6
7
8
9
if(fVal < 0)
  fResult = -fVal;
else
  fResult = fVal;


// vs.

fResult = fabs(fVal);


I'm sure that will be much more comparable.
Check your compiled code. It's possible that the compiler removed negation completely and you've only measured the time it takes to perform 100000000 reads and writes to i in the first case, but didn't know how to remove the call to fabs().

When I make both fVal and fResult volatile doubles, my results are exactly identical across three compilers and two platforms.

compiled code (Linux/clang++)

             fabs                        negation 

main:  
  movq    $0, -8(%rsp)           movq    $0, -8(%rsp)
  cmpq    $99999999, -8(%rsp)    cmpq    $99999999, -8(%rsp)
  jg      .LBB0_3                jg      .LBB0_3
  movsd   fVal(%rip), %xmm0      movsd   fVal(%rip), %xmm0
  andpd   .LCPI0_0(%rip), %xmm0  xorpd   .LCPI0_0(%rip), %xmm0
.LBB0_2:
  movsd   %xmm0, fResult(%rip)   movsd   %xmm0, fResult(%rip)
  incq    -8(%rsp)               incq    -8(%rsp)
  cmpq    $100000000, -8(%rsp)   cmpq    $100000000, -8(%rsp) 
  jl      .LBB0_2                jl      .LBB0_2
.LBB0_3:
  xorl    %eax, %eax             xorl    %eax, %eax
  ret                            ret

        .section        .rodata
.LCPI0_0:
        .quad   -9223372036854775808    # double -0.000000e+00


As you can see, the difference is between an AND and a XOR, which are unlikely to differ in execution time, the rest of the code is identical.
Last edited on
Topic archived. No new replies allowed.