text: > 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