[racket] (Math) Computing the mean is slow in Typed Racket
Hi Laurent,
2013/2/8 Laurent <laurent.orseau at gmail.com>:
> (Just a little testing of the exciting new math lib.)
>
> Is it currently normal that computing the mean of a big list is 10x slower
> compared to the (/ (apply + l) (length l)) method?
>
> The math lib is very recent so I'm not entirely surprised, anyway. Most of
> the time seems to be due to GC.
>
> E.g. (on command line Racket) :
> #lang typed/racket
>
> (require math)
>
> (: n Integer)
> (define n 10000000)
> (: l (Listof Integer))
> (define l (build-list n (λ(x)(random 100))))
>
> (: my-mean ((Listof Integer) -> Number))
> (define (my-mean l)
> (/ (apply + l) (length l)))
>
> (time (mean l))
> (time (my-mean l))
Nice catch. Here is the code for mean from:
collects/math/statistics/private/expected-values.rkt
The function handles general sequences and optional weights.
(: mean (case-> ((Sequenceof Real) -> Real)
((Sequenceof Real) (Option (Sequenceof Real)) -> Real)))
(define (mean xs [ws #f])
(cond [ws (let-values ([(xs ws) (sequences->weighted-samples 'mean xs ws)])
(define n (sum ws))
(cond [(zero? n) +nan.0]
[else (/ (sum (map * xs ws)) n)]))]
[else (let ([xs (sequence->list xs)])
(define n (length xs))
(cond [(zero? n) +nan.0]
[else (/ (sum xs) n)]))]))
In this case ws is #f, so we can ignore the first cond-clause,
and concentrate on:
(let ([xs (sequence->list xs)])
(define n (length xs))
(cond [(zero? n) +nan.0]
[else (/ (sum xs) n)]))]))
Here we see why the mean was slow:
[xs (sequence->list xs)]
This copies the list even though xs is a list already.
Try
[xs (if (list? xs) xs (sequence->list xs))])
and see what the new timings are.
--
Jens Axel Søgaard