haskell / mwc-random

A very fast Haskell library for generating high quality pseudo-random numbers.
http://hackage.haskell.org/package/mwc-random
BSD 2-Clause "Simplified" License
54 stars 25 forks source link

A Pleasant Surprise #86

Closed idontgetoutmuch closed 2 months ago

idontgetoutmuch commented 2 years ago

@Shimuuar I just realised that you made the distributions independent of the RNG :-)

As an experiment I tried the RNG is System.Random and the one in System.Random.MWC:

import System.Random.MWC.Distributions
import Control.Monad.State
import System.Random.Stateful

import qualified System.Random.MWC as MWC

import Options.Applicative
import Data.Semigroup ((<>))
import System.Environment

data Sample = Sample
  { nSamples :: Int
  , mwc      :: Bool
  }

sample :: Parser Sample
sample = Sample
      <$> option auto
          ( long "samples"
         <> short 'n'
         <> help "How many samples"
         <> showDefault
         <> value 1
         <> metavar "INT" )
      <*> switch
          ( long "mwc"
         <> short 'm'
         <> help "Whether to use MWC RNG" )

main :: IO ()
main = generate =<< execParser opts
  where
    opts = info (sample <**> helper)
      ( fullDesc
     <> progDesc "Sample from System.Random or System.Random.MWC"
     <> header "Generate samples from normal either by MWC or Base Library" )

generate :: Sample -> IO ()
generate (Sample n b) =
  if not b
    then do
    let xs = runStateGen_ (mkStdGen 1729) (\g -> replicateM n $ normal 0.0 1.0 g)
    print (sum xs / (fromIntegral n))
    else do
    monadicGen <- MWC.create
    xs <- (replicateM n . normal 0.0 1.0) monadicGen
    print (sum xs / (fromIntegral n))
    return ()

Running 10^7 samples I got

Wandle:monad-bayes dom$ ./TestDist -n 10000000 -m +RTS -s
./TestDist -n 10000000 -m +RTS -s
5.021434306249745e-4
  42,890,490,456 bytes allocated in the heap
         222,688 bytes copied during GC
     478,904,288 bytes maximum residency (12 sample(s))
       4,120,608 bytes maximum slop
             920 MiB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0     10233 colls,     0 par    0.945s   0.995s     0.0001s    0.0055s
  Gen  1        12 colls,     0 par    0.435s   0.588s     0.0490s    0.2606s

  INIT    time    0.000s  (  0.002s elapsed)
  MUT     time   11.729s  ( 11.787s elapsed)
  GC      time    1.380s  (  1.584s elapsed)
  EXIT    time    0.000s  (  0.001s elapsed)
  Total   time   13.109s  ( 13.374s elapsed)

  %GC     time       0.0%  (0.0% elapsed)

  Alloc rate    3,656,769,469 bytes per MUT second

  Productivity  89.5% of total user, 88.1% of total elapsed

Wandle:monad-bayes dom$ ./TestDist -n 10000000 +RTS -s
./TestDist -n 10000000 +RTS -s
-4.4652540900402046e-4
  17,623,212,088 bytes allocated in the heap
          94,880 bytes copied during GC
     965,437,984 bytes maximum residency (13 sample(s))
       3,704,568 bytes maximum slop
            2219 MiB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0      4125 colls,     0 par    1.525s   1.662s     0.0004s    0.0051s
  Gen  1        13 colls,     0 par    0.942s   1.349s     0.1038s    0.5180s

  INIT    time    0.000s  (  0.004s elapsed)
  MUT     time    5.185s  (  5.248s elapsed)
  GC      time    2.466s  (  3.011s elapsed)
  EXIT    time    0.000s  (  0.012s elapsed)
  Total   time    7.651s  (  8.275s elapsed)

  %GC     time       0.0%  (0.0% elapsed)

  Alloc rate    3,399,128,247 bytes per MUT second

  Productivity  67.8% of total user, 63.4% of total elapsed

So very roughly System.Random is twice as fast.

Anyway great for doing this. I am beginning to think it may be time to retire random-fu. I will look and see if there are any distributions in random-fu that can be ported across.

Shimuuar commented 2 years ago

Random-1.2 was a great improvement! Once it was released it become natural to generalize. More generators are always welcome!

idontgetoutmuch commented 2 months ago

I am going to close this - see my PR https://github.com/haskell/mwc-random/pull/90