(oops, forgot to cc: the list) Oh wow, that's interesting. Your code on my computer:
subnormal addition: cpu time: 8156 real time: 8171 gc time: 0 cpu time: 9009 real time: 9035 gc time: 0 cpu time: 7740 real time: 7765 gc time: 0 cpu time: 7276 real time: 7288 gc time: 0 cpu time: 10643 real time: 10743 gc time: 0 normal addition: cpu time: 286 real time: 289 gc time: 0 cpu time: 337 real time: 334 gc time: 0 cpu time: 353 real time: 357 gc time: 0 cpu time: 530 real time: 536 gc time: 0 cpu time: 600 real time: 599 gc time: 0 My computer's pretty old though. According to /proc/cpuinfo, it's a Core Duo (Yonah, http://en.wikipedia.org/wiki/Yonah_(microprocessor) ) 1.8Ghz, c.a. 2006, with a 32-bit OS. Trying again with an Intel Xeon 3Ghz 64-bit machine yields similar results: subnormal addition: cpu time: 7260 real time: 7248 gc time: 0 cpu time: 7312 real time: 7300 gc time: 0 cpu time: 7245 real time: 7233 gc time: 0 cpu time: 7256 real time: 7247 gc time: 0 cpu time: 7285 real time: 7273 gc time: 0 normal addition: cpu time: 248 real time: 251 gc time: 0 cpu time: 292 real time: 295 gc time: 0 cpu time: 240 real time: 240 gc time: 0 cpu time: 248 real time: 251 gc time: 0 cpu time: 296 real time: 296 gc time: 0 Fascinating. I wonder if your machine has better floating point hardware So maybe this is just something to watch out for on older chips. Thanks for looking into this! On Wed, 1 Aug 2012 11:01:13 -0700, Neil Toronto <neil.toro...@gmail.com> wrote: > I wonder how out-of-date the advice is to avoid subnormal numbers. I > don't see any slowdown in my tests. I've written what I think is a good > test program, and I have some experience with squeezing floating-point > performance out of Racket. Can we get others on the mailing list to run > it and report some timings? > > The following test program should ensure (currently) that the JIT > compiles the operations to their fastest forms, that floats don't get > boxed, and that the compiler doesn't inline 1.0. > > > #lang racket > > (require unstable/flonum > racket/flonum > racket/unsafe/ops) > > ;; Don't allow Racket to inline `one': > (define (make-one) 1.0) > (define one (make-one)) > > ;; Store floats here to make sure they don't get boxed: > (define res (make-flvector 1)) > > (printf "subnormal addition:~n") > (for ([_ (in-range 5)]) > (time (for ([_ (in-range 20000000)]) > (unsafe-flvector-set! res 0 (unsafe-fl+ +min.0 +min.0))))) > > (printf "~nnormal addition:~n") > (for ([_ (in-range 5)]) > (time (for ([_ (in-range 20000000)]) > (unsafe-flvector-set! res 0 (unsafe-fl+ one one))))) > > > Running this in DrRacket, with debug info turned off, on a one-year-old > laptop, I get: > > subnormal addition: > cpu time: 80 real time: 88 gc time: 0 > cpu time: 100 real time: 93 gc time: 0 > cpu time: 90 real time: 92 gc time: 0 > cpu time: 110 real time: 106 gc time: 0 > cpu time: 90 real time: 94 gc time: 0 > > normal addition: > cpu time: 90 real time: 87 gc time: 0 > cpu time: 90 real time: 93 gc time: 0 > cpu time: 90 real time: 85 gc time: 0 > cpu time: 100 real time: 100 gc time: 0 > cpu time: 90 real time: 93 gc time: 0 > > Which is obviously the same. > > FWIW, subnormal numbers ensure that subtraction doesn't underflow, no > matter how close two flonums are. The smallest positive flonum is +min.0 > (currently defined in `unstable/flonum'): > > > +min.0 > 4.9406564584125e-324 > > Subtracting the next one from the one after returns something nonzero: > > > (flstep +min.0 1) > 9.8813129168249e-324 > > (flstep +min.0 2) > 1.4821969375237e-323 > > (- (flstep +min.0 2) (flstep +min.0 1)) > 4.9406564584125e-324 > > Neil ⊥ > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users