This is the mail archive of the glibc-bugs@sources.redhat.com mailing list for the glibc 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]

[Bug libc/1059] New: some floating-point math functions inexplicably slow


Hello,

  I wrote some documentation about programming in C
    (home.wanadoo.nl/siward).
  It includes a list of most common math functions from GNU libc.
  Now i have written a section about relative speed of these math functions,
    for which i have measured these speeds
    (executing them a million times each).
  Some of the results i get are significantly slower than i expected
    (especially exp2 and exp10).

  This is on Debian Sarge with standard libc,
    but i doubt that it would be specific to Debian.

  If there is a reason why some functions are so slow compared to others,
    then i would like to know.

  Here is the program i measured with :
    (sometimes i commented a statement out when i was done with it,
     at other times i changed it to next statement i needed,
     you can see it in code
     (that's why fabs is computed, because it is last one to compute)).

----------------------------------------------------------------------------

/* floatspeed.c : measure speed of floating math functions	 */
/* compile with : cd /my/test/c/floatspeed			 */
/*		  cc -lm floatspeed.c -o floatspeed		 */
/* run with	: time floatspeed				 */
/* measure times as sum of sys and usr times		 */
/* run each version thrice and use minimum value	 */
/* noted times are measured on a 200 MHz pentium	 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void dummy( double db ){
  static double keep ;
  static double keep2 ;
  keep = db ;
  /*keep2 = db ;*/
  }

int main( void ){
  int    i = 0 ;
  int    a = 1234 ;
  int    b = 123 ;
  int    c = 0 ;
  double d = 0.000001 ;
  double e = 0 ;
  double f = 0 ;
  double g = 0 ;
	 /* running program takes 9 ms (including one iteration of loop) */
  for( i=0 ; i<1000000 ; i++ ){	 /* with million loop takes 46--49 ms	 */
			 /* with two-million loop takes 82--84 ms */
			 /* INCREMENT+TEST+JUMP	 :   36 ns	 */
    e += d ;		 /* addition takes 84 - (46--49) = 34 -- 37 ms	 */
			 /* DOUBLE ADDITION	 :   34 ns	 */
    dummy(e);		 /* function call takes 211 - 84 = 127ms	 */
			 /* with assignment to keep2 takes 257 - 84 = 173 ms */
			 /* DOUBLE PASS+ASSIGN	 :   46 ns	 */
			 /* CALL		 :   81 ns	 */
    /*c = a / b ;*/	 /* 230 - 211 = 19 ms				 */
			 /* INT ADDITION	 :   19 ns	 */
			 /* INT SUBTRACTION	 :   18 ns	 */
			 /* INT MULTIPLICATION	 :   38 ns	 */
			 /* INT DIVISION	 :   80 ns	 */
    /*f = e * e ;*/	 /* multiplication takes 235 - 211= 24	 */
			 /* DOUBLE MULTIPLY	 :   24 ns (36 *) */
    /*dummy(f);*/	 /* 368, so checks ok (all mults actually done)	 */
    /*f = e / 0.1 ;*/	 /* 462--463 - 235--237 = 228		 */
			 /* DOUBLE DIVIDE	 :  228 ns	 */
    /*f = fabs(e);*/	 /* measured minimum - 211 = result	 */
			 /* SIN			 :  494 ns	 */
			 /* COS			 :  506 ns	 */
			 /* TAN			 :  765 ns	 */
			 /* ASIN		 : 1625 ns	 */
			 /* ACOS		 : 1634 ns	 */
			 /* ATAN		 :  722 ns	 */
			 /* ATAN2		 :  976 ns	 */
			 /* EXP			 : 1125 ns	 */
			 /* EXP2		 : 2612 ns	 */
			 /* EXP10		 : 3258 ns	 */
			 /* LOG			 : 1079 ns	 */
			 /* LOG2		 : 1831 ns	 */
			 /* LOG10		 : 1220 ns	 */
			 /* POW			 : 2372 ns	 */
			 /* SQRT		 :  702 ns	 */
			 /* CBRT		 :  883 ns	 */
			 /* HYPOT		 : 1012 ns	 */
			 /* EXPM1		 : 1033 ns	 */
			 /* LOG1P		 :  870 ns	 */
			 /* CEIL		 :  266 ns	 */
			 /* FLOOR		 :  267 ns	 */
			 /* TRUNC		 :  921 ns	 */
			 /* ROUND		 :  813 ns	 */
			 /* MODF		 :  245 ns	 */
			 /* FMOD		 :  749 ns	 */
			 /* NEXTAFTER		 :  409 ns	 */
			 /* FABS		 :   17 ns	 */
    a = (f > 0) ;	 /* DOUBLE COMPARE	 :   73 ns	 */
    }
  /*printf("i=%d\n",i);*/	 /* initial checks (for bugdetection)	 */
  /*printf("e=%f\n",e);*/
  }

 ----------------------------------------------------------------------------

 And here is the list of unexpected slownesses :

  * Asin and acos are surprisingly slow,
      i would expect them to be as fast as sin et al.

  * exp2 and exp10 are much slower than exp ;
      exp2(x) = 2 ^ x = exp( log(2)) ^ x = exp( log(2) * x ) ,
        and computing it that way explicitly takes 2240 ns ,
        which is faster than using exp2 (2812 ns),
      Also, if more than one exp2() needs to be computed,
        if you do it explicitly, you only need to compute log(2) once,
        thus doubling speed
        (i would expect log(2) to be a defined constant anyway).
     exp10(x) can be computed similarly ,
       and this one takes a lot more time (3258 ns).

 *  Strangely, while log2(x) equals log(x) / log(2),
      log2() is much slower than log()
      (1831 vs 1079 ns).

 * Hypot(a,b) is same as sqrt( a^2 + b^2 ) ,
     which would take 702 + 36 + 36 + 34 = 813 ns ,
     but hypot takes 1012 ns for it.
   Info does not state which amount of extra precision it gains ;
     is it worth it ? does computing two squares lose that much precision ?
    
 * Ceil and floor are slower than i had expected them to be (266 and 267 ns)
   I now realize that i have not yet tried casting double to int,
     so i leave it at that remark.

 * trunc and round are very slow compared to ceil and floor
       (921 and 813 ns versus 266 and 267 ns).
   I tried how fast it is to compare a double to zero (takes 73 ns).
   Trunc can thus be computed as : 'f = (e > 0)? floor(e) : ceil(e) ;'
     which would take circa 366 ns instead of trunc()'s 921 ,
     and round can be computed as : 'f = floor( e + 0.5 ) ;'
       (circa 333 ns instead of round()'s 813).

-----------------------------------------------------------------------------

 I found that dividing a floating point number by two is not especially fast ;
   is there a way to access the exponent and subtract one from it ?

------------------------------------------------------------------------------

 Thanks for your attention.
 Please CC me on replies.
 Have fun !

   Siward
   (home.wanadoo.nl/siward)

------------------------------------------------------------------------------

  "Have you got a light, Mac ?"
  "No, but i have a dark-brown overcoat."
                              -- Bonzo Dog Band

-- 
           Summary: some floating-point math functions inexplicably slow
           Product: glibc
           Version: 2.3.2
            Status: NEW
          Severity: minor
          Priority: P3
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: siward at wanadoo dot nl
                CC: glibc-bugs at sources dot redhat dot com
 GCC build triplet: not relevant
  GCC host triplet: Debian+GNU+Linux
GCC target triplet: not relevant


http://sources.redhat.com/bugzilla/show_bug.cgi?id=1059

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


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