Don't like ads? PRO users don't see any ads ;-)
Guest

parallel PI

By: wuxb on Mar 23rd, 2012  |  syntax: Haskell  |  size: 1.70 KB  |  hits: 50  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. {-# LANGUAGE BangPatterns #-}
  2. import System.Environment
  3. import System.Random
  4. import Data.Word
  5. import System.IO
  6. import Data.Bits
  7. import Text.Printf
  8. import Debug.Trace
  9. import Control.Monad
  10. import Data.List
  11. import Control.Concurrent
  12.  
  13. upBound :: Word32
  14. upBound = 0xffff
  15.  
  16. type IPair = (Integer, Integer)
  17. type WPair = (Word64, Word64)
  18.  
  19. accum :: WPair -> IPair -> IPair
  20. accum (a,b) (p, all) = r
  21.   where
  22.     a2 = a `shiftR` 33
  23.     b2 = b `shiftR` 33
  24.     s2 =
  25.       --traceShow ("a2:",printf "%x" a2 :: String,"b2:",printf "%x" b2 :: String) $
  26.       a2 * a2 + b2 * b2
  27.     p' = if s2 >= 0x4000000000000000 then p else p + 1
  28.     all' = all + 1
  29.     r =
  30.       --traceShow ("s2:",printf "%016x" s2 :: String) $
  31.       p' `seq` all' `seq` (p', all')
  32.  
  33. ncount :: Word64 -> IO IPair
  34. ncount n = do
  35.   (p,all) <- randIter n (0,0)
  36.   return (p * 4, all)
  37.   where
  38.     randIter :: Word64 -> IPair -> IO IPair
  39.     randIter 0 ip = return ip
  40.     randIter n ip = do
  41.       ra <- randomIO
  42.       rb <- randomIO
  43.       let !ip' = accum (ra, rb) ip
  44.       randIter (n - 1) ip'
  45.  
  46. runPI :: Word64 -> IO Double
  47. runPI n = do
  48.   (p,all) <- ncount n
  49.   return $ fromIntegral p / fromIntegral all
  50.  
  51.  
  52. runNPI :: Int -> Word64 -> IO ()
  53. runNPI n pn = do
  54.   mList <- sequence $ take n $ repeat newEmptyMVar
  55.   mapM_ (\m -> forkIO $ runPI pn >>= putMVar m) mList
  56.   mapM_ (\m -> takeMVar m >>= printf "%f") mList
  57.  
  58. main :: IO ()
  59. main = do
  60.   (a:b:_) <- getArgs
  61.   let n = read a :: Int
  62.   let pn = read b :: Word64
  63.   runNPI n pn
  64.  
  65. -- using 2cpus * 4cores * 2threads = 16 virtual cores
  66.  
  67. -- this: all 16 cpu consumes about 30%
  68. -- +RTS -N16 --RTS 1 100000
  69.  
  70. -- +RTS -N16 --RTS 16 100000
  71. -- +RTS -N2 --RTS 1 100000
  72. -- +RTS -N2 --RTS 2 100000