Ah, realized that Gambit makes a difference internally between 1e25 and 10000000000000000000000000 . So added a test also for the latter.
> (->integer-test5)6794405.8> (->flonum-test5)384459.2Def:(define (->integer-test5) (test (->integer 10000000000000000000000000)))(define (->flonum-test5) (test (->flonum 10000000000000000000000000)))
Dear list,I was keeping this question in the back of my mind for several years so taking the occasion to reflect it now:Here follows the result of a simple benchmark of (exact->inexact n) and (exact->inexact (floor n)) where n is a flonum, fixnum or bignum integer, or rational.The code was executed in compiled form, with both safe and interrupts-enabled set and without any consideration to C compiler flags beyond -O1 , to reflect the environment of a typical application (not for instance a specialized number crunching environment).I remember a conversation on this topic like ~4y ago but don't remember any conclusion from it.Looking at these numbers, I think they're great and all you can ask for, with two exceptions, being to-integer conversion of a flonum or integer bignum.To get a better idea I experimented with heap size and live percent setting with those two, and got about the same results.
If you are aware of any definition of |->integer| that would perform much better, please feel free to share!Result:On a laptop CPU core, here's how many of the respective operation Gambit performs per second->integer of an integer (fixnum) 13,804,449->integer of a flonum 260,932 (perhaps performs much better with another definition?)->integer of a rational 10,130,272->integer of an integer (bignum) 598,228 (perhaps performs much better with another definition?)->flonum of an integer (fixnum) 36,550,882->flonum of a flonum 47,756,845->flonum of a rational 334,976->flonum of an integer (bignum) 51,075,409Test code:(declare (block) (standard-bindings) (extended-bindings))(define (noop) (void))(define (->integer n)(lambda ()(inexact->exact (floor n))))(define (->flonum n)(lambda ()(exact->inexact n)))(define (test t #!optional (seconds 5))(let* ((at 0)(th (thread-start! (make-thread (lambda () (let loop ()(t)(set! at (fx+ at 1))(loop)))))))(thread-sleep! seconds)(let ((r at))(thread-terminate! th)(exact->inexact (/ r seconds)))))(define (noop-test) (test noop))(define (->integer-test1) (test (->integer 5 )))(define (->integer-test2) (test (->integer 5. )))(define (->integer-test3) (test (->integer 10/7)))(define (->integer-test4) (test (->integer 1e25)))(define (->flonum-test1) (test (->flonum 5 )))(define (->flonum-test2) (test (->flonum 5. )))(define (->flonum-test3) (test (->flonum 10/7)))(define (->flonum-test4) (test (->flonum 1e25)))Test output:> (time (noop-test))(time (noop-test))5040 ms real time4932 ms cpu time (4896 user, 36 system)no collections2112 bytes allocated6 minor faultsno major faults57985446.4> (time (->integer-test1))(time (->integer-test1))5019 ms real time4884 ms cpu time (4872 user, 12 system)no collections1232 bytes allocatedno minor faultsno major faults13804449.> (time (->integer-test2))(time (->integer-test2))5000 ms real time4792 ms cpu time (4656 user, 136 system)81 collections accounting for 187 ms real time (120 user, 52 system)1607420656 bytes allocated5110 minor faultsno major faults260932.6> (time (->integer-test3))(time (->integer-test3))5015 ms real time4888 ms cpu time (4872 user, 16 system)no collections2240 bytes allocatedno minor faultsno major faults10130272.8> (time (->integer-test4))(time (->integer-test4))5003 ms real time4680 ms cpu time (4536 user, 144 system)158 collections accounting for 401 ms real time (304 user, 60 system)3110877424 bytes allocatedno minor faultsno major faults598228.8> (time (->flonum-test1))(time (->flonum-test1))5011 ms real time4740 ms cpu time (4460 user, 280 system)297 collections accounting for 736 ms real time (524 user, 124 system)5848140864 bytes allocatedno minor faultsno major faults36550882.2> (time (->flonum-test2))(time (->flonum-test2))5001 ms real time4840 ms cpu time (4800 user, 40 system)no collections2088 bytes allocatedno minor faultsno major faults47756845.8> (time (->flonum-test3))(time (->flonum-test3))5005 ms real time4972 ms cpu time (4920 user, 52 system)65 collections accounting for 147 ms real time (120 user, 16 system)1286350504 bytes allocatedno minor faultsno major faults334976.6> (time (->flonum-test4))(time (->flonum-test4))5002 ms real time4876 ms cpu time (4848 user, 28 system)no collections2080 bytes allocatedno minor faultsno major faults51075409.82013/4/24 Bradley Lucier <lucier@math.purdue.edu>Yes. Fixnums are always "immediate" (not boxed) values.On 04/24/2013 01:33 PM, Mikael wrote:
Hi Brad!
2013/4/24 Bradley Lucier <lucier@math.purdue.edu>
On 04/24/2013 12:37 PM, Zhen Shen wrote:
[...]> Now, doing (declare (flonum)) at the top level, does this stop gambitNo. Gambit keeps flonums unboxed inside a basic block, whenever there's
> from boxing flonums across function calls?
a jump (or the possibility of a jump), Gambit boxes up all the
still-needed flonums.
What about fixnums, would they remain unboxed in a loop?
Use (declare (not safe)) and flonum-specific operations to keep flonums unboxed in a basic block. There's no way to keep them unboxed across jumps. (With generic operations, flonums are boxed even in a basic block.)
Also btw, are there any tricks that can be applied to make it keep flonums and fixnums unboxed in loops, like, (declare (not interrupts-enabled)) or (not safe)?
Or, you can use an f64vector as an explicit "box" for your flonum and write monstrous code like this.
(define (Array-sum a)
(f64vector-ref (Array-reduce (lambda (result y)
(f64vector-set! result 0 (fl+ (f64vector-ref result 0) y))
result)
(f64vector 0.)
a)
0))
Brad