[racket] Fun with denormalized floating point numbers

From: Michael Wilber (mwilber at uccs.edu)
Date: Wed Aug 1 14:27:48 EDT 2012

Oh whoops, you're right. (expt 2 -1050) is an exact number so I'm taking
a big performance hit from using exact numbers.


But (expt 2.0 -1000) is inexact. To keep it from quitting
instantaneously, I added a few 0s to the definition:

(define (test value)
  (let loop ([count 10000000] [x value])
    (when (count . > . 0)
      (loop (sub1 count)
            (* value 0.999999999999)))))

And now it's even more pronounced.

> (time-it (expt 2.0 -1000))
181 - 307
> (time-it (expt 2.0 -1050))
2578 - 4184

Am I just seeing things? :)

On Wed, 1 Aug 2012 18:30:10 +0200, Tobias Hammer <tobias.hammer at dlr.de> wrote:
> But why ...
>
> (time-it (exact->inexact (expt 2 -1050)) test)
> > 0 - 1
>
> (time-it (exact->inexact (expt 2 -1000)) test)
> > 0 - 0
>
> ... and ...
>
> (time-it (expt 2 -1050) test_2)
> > 26 - 28
> (time-it (expt 2 -1000) test_2)
> > 3 - 4
>
> (time-it (expt 2 -1050) test)
> > 26 - 28
> (time-it (expt 2 -1000) test)
> > 3 - 4
>
> Careful with exact-inexact conversions?
>
>
> =================
>
> #lang racket
>
> (provide (all-defined-out))
>
> (define (test value)
>    ;; Perform 100,000 floating point multiplies.
>    ;; (Only side effect is time)
>    (let loop ([count 5000] [x value])
>      (when (count . > . 0)
>        (loop (sub1 count)
>              (* value 0.999999999999)))))
>
>
> (define (test_2 value)
>    (let loop ([count 5000] [x value])
>      (when (count . > . 0)
>        (exact->inexact value)
>        (loop (sub1 count)
>              value))))
>
>
> (define (time-it start-value fun)
>    ;; Run (test start-value) 100 times and print
>    ;; 5th and 95th percentile
>    (define unsorted-times
>      (for/list ([i (in-range 100)])
>        (define-values (results cputime realtime gctime)
>          (time-apply fun (list start-value)))
>        realtime))
>    (define times (sort unsorted-times <))
>    (define 5p (list-ref times 5))
>    (define 95p (list-ref times 95))
>    (printf "~a - ~a\n" 5p 95p))
>
>
>
>
> On Wed, 01 Aug 2012 17:48:25 +0200, Michael Wilber <mwilber at uccs.edu>
> wrote:
>
> > So here's something fun to look out for in your own programs.
> >
> > On my slower 32-bit machine, very small numbers are much slower than
> > slightly less small numbers.
> >
> >> (time-it (expt 2 -1000))
> > 126 - 235
> >> (time-it (expt 2 -1050))
> > 1187 - 2071
> >
> > On my faster 64-bit machine, the performance difference is an order of
> > magnitude:
> >
> >> (time-it (expt 2 -1000))
> > 55 - 57
> >> (time-it (expt 2 -1050))
> > 777 - 831
> >
> > This also happens in C, Java, Python, Javascript, and presumably any
> > language that uses IEEE754 floating point numbers.
> >
> > Careful with those small numbers!
> >
> >
> > ;; fun-with-denormalized-floats.rkt ;;;;;;;;;;;;;;;;;;;;;;;;
> > #lang racket
> >
> > (provide (all-defined-out))
> >
> > (define (test value)
> >   ;; Perform 100,000 floating point multiplies.
> >   ;; (Only side effect is time)
> >   (let loop ([count 100000] [x value])
> >     (when (count . > . 0)
> >       (loop (sub1 count)
> >             (* value 0.999999999999)))))
> >
> >
> > (define (time-it start-value)
> >   ;; Run (test start-value) 100 times and print
> >   ;; 5th and 95th percentile
> >   (define unsorted-times
> >     (for/list ([i (in-range 100)])
> >       (define-values (results cputime realtime gctime)
> >         (time-apply test (list start-value)))
> >       realtime))
> >   (define times (sort unsorted-times <))
> >   (define 5p (list-ref times 5))
> >   (define 95p (list-ref times 95))
> >   (printf "~a - ~a\n" 5p 95p))
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
>
>
> --
> ---------------------------------------------------------
> Tobias Hammer
> DLR / Institute of Robotics and Mechatronics
> Tel.: 08153/28-1487
> Mail: tobias.hammer at dlr.de

Posted on the users mailing list.