#2280: randomR too slow
-----------------------------------------+----------------------------------
    Reporter:  guest                     |       Owner:                  
        Type:  run-time performance bug  |      Status:  new             
    Priority:  normal                    |   Component:  libraries/random
     Version:  6.8.2                     |    Severity:  normal          
    Keywords:  randomR                   |    Testcase:                  
Architecture:  x86                       |          Os:  Linux           
-----------------------------------------+----------------------------------
 randomR is considerably slower than implementing it manually. Maybe I have
 not re-implemented it precisely, maybe it is just not inlined.

 {{{
 module Main (main) where

 import System.Random (RandomGen(..), randomR, )
 import qualified Data.ByteString as B

 newtype KnuthRandomGen = KnuthRandomGen Int

 {-# INLINE knuthFactor #-}
 knuthFactor :: Int
 knuthFactor = 40692

 {-# INLINE knuthModulus #-}
 knuthModulus :: Int
 knuthModulus = 2^(31::Int)-249

 -- we have to split the 32 bit integer in order to avoid overflow on
 multiplication
 knuthSplit :: Int
 knuthSplit = succ $ div knuthModulus knuthFactor

 knuthSplitRem :: Int
 knuthSplitRem = knuthSplit * knuthFactor - knuthModulus

 instance RandomGen KnuthRandomGen where
    {-# INLINE next #-}
    next (KnuthRandomGen s) =
       -- efficient computation of @mod (s*knuthFactor) knuthModulus@
 without Integer
       let (sHigh, sLow) = divMod s knuthSplit
       in  (s, KnuthRandomGen $ flip mod knuthModulus $
                    knuthSplitRem*sHigh + knuthFactor*sLow)
    {-# INLINE split #-}
    split (KnuthRandomGen s) =
       (KnuthRandomGen (s*s), KnuthRandomGen (13+s))
    {-# INLINE genRange #-}
    genRange _ = (1, pred knuthModulus)


 main :: IO ()
 main =
    do
       -- for comparison: that's very fast
       putStrLn "constant"
       B.writeFile "random.out" $ fst $
           B.unfoldrN 10000000
              (\g0@(KnuthRandomGen s) -> Just (fromIntegral s, g0))
              (KnuthRandomGen 1)

       -- 3 seconds on my machine
       putStrLn "immediate"
       B.writeFile "random.out" $ fst $
           B.unfoldrN 10000000
              (\g0 -> let (w,g1) = next g0
                      in  Just (fromIntegral (mod w 256), g1))
              (KnuthRandomGen 1)

       -- 10 seconds on my machine
       putStrLn "randomR"
       B.writeFile "random.out" $ fst $
           B.unfoldrN 10000000
              (\g0 -> Just (let (w,g1) = randomR (0,255) g0
                            in  (fromIntegral (w::Int), g1)))
              (KnuthRandomGen 1)


 {-
 ghc -o dist/build/randomtest -O -Wall -package bytestring-0.9.0.5 -ddump-
 simpl-iterations speedtest/RandomTest.hs
 -}
 {-
 bytestring-0.9.0.1 as shipped with GHC-6.8.2 does not inline
 Data.ByteString.unfoldrN
 -}

 }}}

 Is this related to Ticket 427?

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2280>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to