This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Floating point performance issue


On 20/12/2011 11:20, Ico wrote:
* On Tue Dec 20 11:05:17 +0100 2011, Marcin MirosÅaw wrote:

W dniu 20.12.2011 10:52, Ico pisze:

I am able to reproduce this on multiple i686 boxes using various gcc versions
(4.4, 4.6). Compiling on x86_64 does not show this behaviour.

Is anybody able to reproduce this issue, and how can this be explained ?

I can reproduce such situation too. I can only guess this happens because on i686 default is mfpmath=387, on x86_64 default is mfpmath=sse. If you compile your code using "-O3 -mfpmath=sse -march=native<or something what else what have support for sse>" then booth times will be almost equal.

Thanks for testing this.


Still, I'm not sure if sse is part of the problem and/or solution.

I have been reducing the program to see what the smallest code is that still
shows this behaviour. Latest version is below.


$ gcc -msse -mfpmath=sse -O3 -march=native test.c $ time ./a.out 0.9

real	0m2.653s
user	0m2.648s
sys	0m0.002s
$ time ./a.out 0.001

real	0m0.144s
user	0m0.140s
sys	0m0.002s


/* gcc -msse -mfpmath=sse -O3 -march=native test.c */


#include<stdlib.h>

#define S 20000000

int main(int argc, char **argv)
{
         int j;
         double a = 0;
         double b = 1;
         double f = atof(argv[1]);

         for(j=0; j<S; j++) {
                 a = b * f;
                 b = a * f;
         }

         return a;
}

I've just tried this code (on an i7-920, 64-bit Linux), compiled with gcc 4.5.1, command line:


gcc fp.c -o fp -O2 -Wa,-ahdls=fp.lst

"time ./fp 0.50" takes 0.088 seconds, but "time ./fp 0.51" takes 2.584 seconds.

The inner loop is using mmx, as can be seen from the listing file:

  18                    .L2:
  19 0020 660F28CA              movapd  %xmm2, %xmm1
  20 0024 83E801                subl    $1, %eax
  21 0027 F20F59C8              mulsd   %xmm0, %xmm1
  22 002b 660F28D1              movapd  %xmm1, %xmm2
  23 002f F20F59D0              mulsd   %xmm0, %xmm2
  24 0033 75EB                  jne     .L2

But what is more interesting, is if I compile with the "-ffast-math" flag, exactly the same listing file is generated, but the program runs at about 0.088 seconds for any input.

You can get a clue as to the reason behind this if you add a "printf("%g\t%g\n", a, b)" statement at the end of the program. When I then run "fp.slow" (no "-ffast-math" flag) and "fp.fast" (with "-ffast-math") I get:

[david@davidquad c]$ time ./fp.slow 0.50
0       0.000000

real    0m0.088s
user    0m0.086s
sys     0m0.000s

[david@davidquad c]$ time ./fp.slow 0.51
4.94066e-324    0.000000

real    0m2.575s
user    0m2.567s
sys     0m0.000s

[david@davidquad c]$ time ./fp.fast 0.50
0       0.000000

real    0m0.087s
user    0m0.086s
sys     0m0.000s
[david@davidquad c]$ time ./fp.fast 0.51
0       0.000000

real    0m0.087s
user    0m0.087s
sys     0m0.000s


The key point here is that without the "-ffast-math" flag, rounding effects mean that with input values strictly more than 0.5, but less than 1, end up with "a" being stuck on a very small but non-zero value. With input values of 0.5 or less, "a" quickly reduces to 0, and the processor short-cuts the multiply. With the "-ffast-math" flag active, my guess is that the program header sets up different rounding or saturation modes on the processor, avoiding this issue.


mvh.,

David


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]