# Difference between revisions of "Concurrency demos/Zeta"

From HaskellWiki

m (zipWithM thread (repeat s) = mapM (thread s)) |
(Add a Control.Parallel.Strategies version) |
||

Line 48: | Line 48: | ||

</haskell> |
</haskell> |
||

+ | === Or using Strategies === |
||

+ | Replace the <hask>Control.Concurrent...</hask> imports by |
||

+ | <haskell> |
||

+ | import Control.Parallel.Strategies |
||

+ | </haskell> |
||

+ | and replace main by |
||

+ | <haskell> |
||

+ | main :: IO () |
||

+ | main = do |
||

+ | (t, n, s) <- getParams |
||

+ | let ranges = cut (1, n) t |
||

+ | results = map (zetaRange s) ranges `using` parList rnf |
||

+ | putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ] |
||

+ | print (sum (concat results)) |
||

+ | </haskell> |
||

== Benchmarks == |
== Benchmarks == |

## Revision as of 01:36, 29 November 2006

## A simple example of parallelism in Haskell

This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.

```
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Monad
import Data.Complex
import System.Environment
-- Return the list of the terms of the zeta function for the given range.
-- We don't sum the terms here but let the main thread sum the lists returned
-- by all the other threads so as to avoid accumulating rounding imprecisions.
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]
cut :: (Integral a) => (a, a) -> a -> [(a, a)]
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)
where
(size, modulo) = y `divMod` n
mine = size + modulo
cut' _ _ 0 = []
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size')
getParams :: IO (Int, Int, Complex Double)
getParams = do
argv <- getArgs
case argv of
(t:n:s:[]) -> return (read t, read n, read s)
_ -> error "usage: zeta <nthreads> <boundary> <s>"
main :: IO ()
main = do
(t, n, s) <- getParams
childs <- mapM (thread s) (cut (1, n) t)
results <- mapM takeMVar childs
print (sum (concat results))
where
thread s range = do
putStrLn ("Starting thread for range " ++ show range)
mvar <- newEmptyMVar
forkIO (putMVar mvar (zetaRange s range))
return mvar
```

### Or using Strategies

Replace the `Control.Concurrent...`

imports by

```
import Control.Parallel.Strategies
```

and replace main by

```
main :: IO ()
main = do
(t, n, s) <- getParams
let ranges = cut (1, n) t
results = map (zetaRange s) ranges `using` parList rnf
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]
print (sum (concat results))
```

## Benchmarks

Insert benchmarks here! :-)