[gambit-list] Simple benchmark of |->integer| and |->flonum| on integer, flonum and rational input. For the further if you have any idea of a definition faster than (inexact->exact (floor n)) feel free to share :)

Mikael mikael.rcv at gmail.com
Wed Apr 24 17:17:37 EDT 2013


2013/4/24 Bradley Lucier <lucier at math.purdue.edu>

>  OK, data is good.
>
> Here is what Gambit expands your code to, with some annotations:
>
>  heine:~/Downloads> gsc -c -expansion conversion.scm
> Expansion:
>
> (define noop (lambda () #!void))
>
>  The following implies that gsc could expand (floor n) better as:
>
> (cond ((fixnum? n) n)
>       ((and ('#<procedure #2 ##flonum?> n) ('#<procedure #3 ##flfinite?>
> n)) ('#<procedure #4 ##flfloor> n))
>       (else ('#<procedure #5 floor> n))))
>
> and it could expand inexact->exact better (after defining flfixnum?) as
>
> (cond ((fixnum? n) n)
>       ((and (flonum? n) (flinteger? n) (flfixnum? n)) (flonum->fixnum n))
>       (else (<inexact->exact> n))
>

Wait, is this a feature suggestion for Gambit, did I understand you right
by that?

(As in, currently Gambit expands it another way and now you suggest this
particular way that you've given here)


> (define ->integer
>   (lambda (n)
>     (lambda ()
>       (let ((temp.5 (if (and ('#<procedure #2 ##flonum?> n) ('#<procedure
> #3 ##flfinite?> n))
>                         ('#<procedure #4 ##flfloor> n)
>                         ('#<procedure #5 floor> n))))
>         (if ('#<procedure #6 ##fixnum?> temp.5) temp.5 ('#<procedure #7
> inexact->exact> temp.5))))))
>
> (define ->flonum
>   (lambda (n)
>     (lambda ()
>       (if ('#<procedure #6 ##fixnum?> n)
>           ('#<procedure #8 ##fl<-fx> n)
>           (if ('#<procedure #2 ##flonum?> n) n ('#<procedure #9
> exact->inexact> n))))))
>
>  This following machinery seems pretty heavy.  I'd suggest
>
> (define (test t #!optional (seconds 1.))
>   (let loop ((n 1))
>     (let ((start-time (cpu-time)))
>       (do ((i 0 (fx+ i 1)))
>       ((fx= i n))
>     (t))
>       (let ((end-time (cpu-time)))
>     (if (<= seconds (fl- end-time start-time))
>         (pp (/ n (fl- end-time start-time)))
>         (loop (fx* n 2)))))))
>
>
> (define test
>   (lambda (t #!optional (seconds 5))
>     (let ((at ('#<procedure #10 ##box> 0)))
>       (let ((th (thread-start!
>                  (make-thread
>                   (lambda ()
>                     (letrec ((loop (lambda (t at)
>                                      (let ((begin-temp.1 (t)))
>                                        (let ((begin-temp.0
>                                               ('#<procedure #11 ##set-box!>
>                                                at
>                                                (let ((temp.7 ('#<procedure
> #12 ##unbox> at)))
>                                                  (if ('#<procedure #6
> ##fixnum?> temp.7)
>                                                      (let ((temp.9
> ('#<procedure #13 ##fx+?> temp.7 1)))
>                                                        (if temp.9 temp.9
> ('#<procedure #14 fx+> temp.7 1)))
>                                                      ('#<procedure #14
> fx+> temp.7 1))))))
>                                          (loop t at))))))
>                       (loop t at)))))))
>         (let ((begin-temp.3 (thread-sleep! seconds)))
>           (let ((r ('#<procedure #12 ##unbox> at)))
>             (let ((begin-temp.2 (thread-terminate! th)))
>               (let ((temp.12 (if (and ('#<procedure #2 ##flonum?> seconds)
> ('#<procedure #2 ##flonum?> r))
>                                  ('#<procedure #15 ##fl/> r seconds)
>                                  ('#<procedure #16 /> r seconds))))
>                 (if ('#<procedure #6 ##fixnum?> temp.12)
>                     ('#<procedure #8 ##fl<-fx> temp.12)
>                     (if ('#<procedure #2 ##flonum?> temp.12) temp.12
> ('#<procedure #9 exact->inexact> temp.12)))))))))))
>
>  With that, my rates are (first for void, then the four ->integer, then
> the four ->flonum):
>
> 76082403.02475469
>
> 18077766.69130593
> 2113932.395354323
> 12632656.242117403
> 1560283.434666285
>
> 34377410.006859235
> 69323006.15509051
> 1230645.7282318561
> 69180045.37858963
>
> And, with (declare (not safe)) I get
>
> 105510445.88390666
>
> 18807367.927219782
> 2444080.701261633
> 13230418.609566122
> 1569627.036643679
>
> 47124065.98183112
> 92942772.26488659
> 1327228.230636181
> 92942772.26488681
>


Basically, nice numbers!



Numbers that are in the millions are good really.

I'd love to see the flonum to integer speed a bit higher (yellow above), I
mean in C that's just  double d; int i = (int) d; .

I tried it out in C and got 47,619,047 per second, code below.

Now, Gambit does lots of typechecking and boxing and stuff, though
shouldn't like 5-10 million per second be reachable?

That I got 10-50 million per second of the other operations that do
basically the same thing as this in Gambit led me to think that there might
be some other definition of |->integer| that could get to this result,
though not clear right now what that definition would be.

Addressed this because I thought it's like a generally relevant thing.



Brgds


C test:

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

int main() {
double d = (double)rand()/100.0;
 int x;
int i;
 for (i = 0; i < 1000000000; i++) {
x = (int) d;
 }
}


g++ cfile.c; time ./a.out
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20130425/0e5c9986/attachment.htm>


More information about the Gambit-list mailing list