[Haskell-cafe] Re: True Random Numbers
mokus at deepbondi.net
mokus at deepbondi.net
Thu Apr 8 10:06:41 EDT 2010
> Is there a way to get multiple random numbers without having to
> replicateM?
>
> While comparing the random-fu interface with Control.Monad.Random (both
> using StdGen), I noticed that while performance is comparable, using
> getRandomRs to get a list of random numbers is a lot faster than
> replicating uniform (or getRandomR for that matter). I don't know if
> this kind of speed gain makes sense for random-fu though.
I have been attempting to replicate this. What sort of a performance
difference are you seeing, and are you using the hackage-released version
of random-fu or the darcs one? The darcs release is, overall, a fair bit
faster than the current hackage release. Depending on the particular way
that I sample my RVars (eg, replicateM n (sample ...) vs sample
(replicateM n ...)), I am seeing the random-fu version of my little
benchmark run anywhere from 30% faster to 25% slower than
Control.Monad.Random.getRandomRs (for 64000 uniform Double samples). The
same benchmark using random-fu-0.0.3.2 shows it consistently about 33%
slower than getRandomRs.
In case you're interested, this is the (criterion) benchmark I used (with
count = 64000, and in the first bgroup 'src' is an "IORef StdGen"):
> [ bgroup "replicateM"
> [ bench "randomRIO" $ do
> xs <- replicateM count (randomRIO (10,50) :: IO Double)
> sum xs `seq` return ()
>
> , bench "uniform A" $ do
> xs <- replicateM count
> (sampleFrom src (uniform 10 50) :: IO Double)
> sum xs `seq` return ()
> , bench "uniform B" $ do
> xs <- sampleFrom src
> (replicateM count (uniform 10 50)) :: IO [Double]
> sum xs `seq` return ()
> ]
>
> , bgroup "pure StdGen"
> [ bench "getRandomRs" $ do
> src <- newStdGen
> let (xs, _) = CMR.runRand (CMR.getRandomRs (10,50)) src
> sum (take count xs :: [Double]) `seq` return ()
> , bench "RVarT, State - sample replicateM" $ do
> src <- newStdGen
> let (xs, _) = runState
> (sample (replicateM count (uniform 10 50))) src
> sum (xs :: [Double]) `seq` return ()
> , bench "RVarT, State - replicateM sample" $ do
> src <- newStdGen
> let (xs, _) = runState
> (replicateM count (sample (uniform 10 50))) src
> sum (xs :: [Double]) `seq` return ()
> ]
If the problem is worse than this benchmark indicates, or if this
benchmark shows radically different results on a different platform (I'm
running on Mac OS 10.6 with GHC 6.12.1), I'd love to hear about it. I
could certainly imagine cases where the choice of monad in which to sample
makes things quite slow. In the above case, I was using IO in the first
bgroup and State StdGen in the second.
As for whether an optimization like getRandomRs would benefit the
random-fu library: I have tried a few different times to implement list
or vector primitives and the corresponding high-level interfaces for
sampling many variables at once, but have not yet come up with a version
that actually made anything faster. I'm more than happy to accept patches
if someone comes up with one, though! ;)
-- James
More information about the Haskell-Cafe
mailing list