[gambit-list] number->integer

Bradley Lucier lucier at math.purdue.edu
Thu Oct 30 12:04:11 EDT 2008


On Oct 30, 2008, at 9:33 AM, David Rush wrote:

>
> On Thu, Oct 30, 2008 at 2:32 AM, Marc Feeley  
> <feeley at iro.umontreal.ca> wrote:
>> (define (f0 x)  ;; 4600 ns per call
>>  (declare (standard-bindings))
>>  (inexact->exact (truncate x)))
>>
>> (define (f1 x)  ;; 4000 ns per call
>>  (declare (standard-bindings))
>>  (truncate (inexact->exact x)))
>
> This is *really* interesting w/rt the implementation model of floats.
> I would guess that this means that inexact->exact just flips an
> exactness bit in Gambit's float representation, no? I would have
> thought that truncating an exact rational would be rather expensive in
> comparison to normalizing a floating integer. I'd think that
> truncating a float would be relatively cheap.
>
> What's really going on here?


I don't quite get Marc's timings; let's look at the expansion:

[descartes:~/Desktop] lucier% cat fix.scm
(define (f0 x)  ;; 4600 ns per call
  (declare (standard-bindings))
  (inexact->exact (truncate x)))

(define (f1 x)  ;; 4000 ns per call
  (declare (standard-bindings))
  (truncate (inexact->exact x)))

(define (test0 n x)
   (declare (standard-bindings)
            (extended-bindings)
            (fixnum)
            (not safe))
   (do ((i 0 (+ i 1)))
       ((= i n))
     (f0 x)))

(define (test1 n x)
   (declare (standard-bindings)
            (extended-bindings)
            (fixnum)
            (not safe))
   (do ((i 0 (+ i 1)))
       ((= i n))
     (f1 x)))

[descartes:~/Desktop] lucier% gsc -keep-c -expansion -cc-options "- 
save-temps" fix.scm
Expansion:

(define f0
   (lambda (x)
     (let ((temp.5 (if (and ('#<procedure #2 ##flonum?> x)  
('#<procedure #3 ##flfinite?> x)) ('#<procedure #4 ##fltruncate> x)  
(truncate x))))
       (if ('#<procedure #5 ##fixnum?> temp.5) temp.5 (inexact->exact  
temp.5)))))

(define f1
   (lambda (x)
     (let ((temp.7 (if ('#<procedure #5 ##fixnum?> x) x (inexact- 
 >exact x))))
       (if (and ('#<procedure #2 ##flonum?> temp.7) ('#<procedure #3  
##flfinite?> temp.7)) ('#<procedure #4 ##fltruncate> temp.7) (truncate  
temp.7)))))

(define test0
   (lambda (n x)
     (letrec ((do-temp.0
               (lambda (n x i)
                 (if ('#<procedure #6 ##fx=> i n)
                     #!void
                     (let ((begin-temp.1 (f0 x)))
                       (let ((i ('#<procedure #7 ##fx+> i 1)))
                         (if ('#<procedure #6 ##fx=> i n) #!void (let  
((begin-temp.1 (f0 x))) (do-temp.0 n x ('#<procedure #7 ##fx+> i  
1))))))))))
       (do-temp.0 n x 0))))

(define test1
   (lambda (n x)
     (letrec ((do-temp.2
               (lambda (n x i)
                 (if ('#<procedure #6 ##fx=> i n)
                     #!void
                     (let ((begin-temp.3 (f1 x)))
                       (let ((i ('#<procedure #7 ##fx+> i 1)))
                         (if ('#<procedure #6 ##fx=> i n) #!void (let  
((begin-temp.3 (f1 x))) (do-temp.2 n x ('#<procedure #7 ##fx+> i  
1))))))))))
       (do-temp.2 n x 0))))

[descartes:~/Desktop] lucier% gsi
Gambit v4.3.0

 > (load "fix")
"/Users/lucier/Desktop/fix.o2"
 > (time (test1 1000000 0.2))
(time (test1 1000000 .2))
     2237 ms real time
     2218 ms cpu time (2164 user, 54 system)
     1265 collections accounting for 1027 ms real time (986 user, 21  
system)
     400000000 bytes allocated
     no minor faults
     no major faults
 > (time (test0 1000000 0.2))
(time (test0 1000000 .2))
     4523 ms real time
     4490 ms cpu time (4359 user, 131 system)
     3907 collections accounting for 3122 ms real time (3007 user, 56  
system)
     1232000000 bytes allocated
     no minor faults
     no major faults
 >
*** EOF again to exit
[descartes:~/Desktop] lucier% gsi -:m100000
Gambit v4.3.0

 > (load "fix")
"/Users/lucier/Desktop/fix.o2"
 > (time (test1 1000000 0.2))
(time (test1 1000000 .2))
     1453 ms real time
     1437 ms cpu time (1237 user, 200 system)
     3 collections accounting for 3 ms real time (3 user, 0 system)
     400000000 bytes allocated
     no minor faults
     no major faults
 > (time (test0 1000000 0.2))
(time (test0 1000000 .2))
     1372 ms real time
     1363 ms cpu time (1346 user, 17 system)
     12 collections accounting for 11 ms real time (11 user, 0 system)
     1232138320 bytes allocated
     no minor faults
     no major faults
 >

It appears that once one defines a large enough minimum heap size to  
basically remove gc time, the largest time hog is the intermodule  
calls and returns for inexact->exact and truncate.  You can see that  
working with rational numbers adds a lot to the heap allocation.

Brad



More information about the Gambit-list mailing list