https://wiki.haskell.org/api.php?action=feedcontributions&user=Mux&feedformat=atomHaskellWiki - User contributions [en]2024-03-19T12:21:15ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=GHC/Using_rules&diff=9875GHC/Using rules2007-01-03T17:29:25Z<p>Mux: Typo fix</p>
<hr />
<div>== Using Rules in GHC ==<br />
<br />
GHC's rewrite rules (invoked by the RULES pragma) offer a powerful way to optimise your program. This page is a place for people who use rewrite rules to collect thoughts about how to use them.<br />
<br />
If you aren't already familiar with RULES, read this stuff first:<br />
* [http://www.haskell.org/ghc/docs/latest/html/users_guide/rewrite-rules.html The relevant section of the GHC user manual]<br />
* [http://research.microsoft.com/%7Esimonpj/Papers/rules.htm Playing by the rules: rewriting as a practical optimisation technique in GHC]. This paper, from the 2001 Haskell workshop, describes the idea of rewrite rules.<br />
<br />
=== Advice about using rewrite rules ===<br />
<br />
* Remember to use the flag <tt>-fglasgow-exts</tt> and the optimisation flag <tt>-O</tt><br />
* Use the flag <tt>-ddump-simpl-stats</tt> to see how many rules actually fired.<br />
* For even more detail use <tt>-ddump-simpl-stats -ddump-simpl-iterations</tt> to see the core code at each iteration of the simplifer. Note that this produces '''lots''' of output so you'll want to direct the output to a file or pipe it to <tt>less</tt>. Looking at the output of this can help you figure out why rules are not firing when you expect them to do so.<br />
* Another tip for discovering why rules do not fire, is to use the flag <tt>-dverbose-core2core</tt>, which (amongst other things) produces the AST after every rule is fired. This can help you to examine whether one rule is creating an expression that thereby prevents another rule from firing, for example.<br />
* You need to be careful that your identifiers aren't inlined before your RULES have a chance to fire. To control this we add an <tt>INLINE [1]</tt> pragma to identifiers we want to match in rules, to ensure they haven't disappeared by the time the rule matching comes around.<br />
<br />
=== Example: <tt>map</tt> ===<br />
<br />
(This example code is taken from GHC's <tt>base/GHC/Base.lhs</tt> module.)<br />
<br />
map :: (a -> b) -> [a] -> [b]<br />
map _ [] = []<br />
map f (x:xs) = f x : map f xs<br />
<br />
mapFB :: (elt -> lst -> lst) -> (a -> elt) -> a -> lst -> lst<br />
{-# INLINE [0] mapFB #-}<br />
mapFB c f x ys = c (f x) ys<br />
<br />
The rules for map work like this.<br />
<br />
Up to (but not including) phase 1, we use the <tt>"map"</tt> rule to<br />
rewrite all saturated applications of map with its build/fold<br />
form, hoping for fusion to happen.<br />
In phase 1 and 0, we switch off that rule, inline build, and<br />
switch on the <tt>"mapList"</tt> rule, which rewrites the foldr/mapFB<br />
thing back into plain map.<br />
<br />
It's important that these two rules aren't both active at once<br />
(along with build's unfolding) else we'd get an infinite loop<br />
in the rules. Hence the activation control below.<br />
<br />
The <tt>"mapFB"</tt> rule optimises compositions of map.<br />
<br />
This same pattern is followed by many other functions:<br />
e.g. append, filter, iterate, repeat, etc.<br />
<br />
{-# RULES<br />
"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)<br />
"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f<br />
"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g)<br />
#-}<br />
<br />
== Questions ==<br />
<br />
=== Order of rule-matching ===<br />
<br />
For example, let's say we have two rules<br />
"f->g" forall x y . f x (h y) = g x y<br />
"h->g" forall x . h x = g 0 x<br />
and a fragment of the AST corresponding to<br />
f a (h b)<br />
<br />
Which rule will fire? "f->g" or "h->g"? (Each rule disables the other.)<br />
<br />
Answer: rules are matched against the AST for expressions basically<br />
''bottom-up'' rather than top-down. In this example, "h->g" is the rule<br />
that fires. But due to the nature of inlining and so on, there are<br />
absolutely no guarantees about this kind of behaviour. If you really<br />
need to control the order of matching, phase control is the only<br />
reliable mechanism.<br />
<br />
=== Pair rules ===<br />
<br />
It is often useful to provide two implementations of a function, and<br />
have rewrite rules pick which version to use depending on context. In<br />
both GHC's foldr/build fusion, and more extensively in Data.ByteString's<br />
stream fusion system, pair rules are used to allow the compiler to<br />
choose between two implementations of a function.<br />
<br />
Consider the rules:<br />
<br />
<haskell><br />
"FPS length -> fused" [~1]<br />
length = F.strConsumerBi F.lengthS<br />
<br />
"FPS length -> unfused" [1]<br />
F.strConsumerBi F.lengthS = length<br />
</haskell><br />
<br />
This rule pair tells the compiler to rewrite occurences of "length" to a<br />
stream-fusible form in early simplifications phases, hoping for fusion<br />
to happen. However, if by phase 1 (remember that phases count down from<br />
4), the fusible form remains unfused, it is better to rewrite it back to<br />
the unfused-but-fast implementation of length. A similar trick is used<br />
for "map" in the baes libraries.<br />
<br />
As we want to match "length" in the rules, we need to ensure that it<br />
isn't inlined too soon:<br />
<br />
<haskell><br />
length :: ByteString -> Int<br />
length (PS _ _ l) = assert (l >= 0) $ l<br />
{-# INLINE [1] length #-}<br />
</haskell><br />
<br />
and we need "strConsumerBi" to stick around for even longer:<br />
<br />
<haskell><br />
strConsumerBi :: (Stream -> a) -> (ByteString -> a)<br />
strConsumerBi f = f . readStrUp<br />
{-# INLINE [0] strConsumerBi #-}<br />
<br />
lengthS :: Stream -> Int <br />
lengthS ...<br />
{-# INLINE [0] lengthS #-}<br />
</haskell><br />
<br />
Pair rules thus provide a useful mechanism to allow a library to provide<br />
multiple implementations of a function, picking the best one to use<br />
based on context.<br />
<br />
=== Custom specialisation rules ===<br />
<br />
Another use for rules is to replace a particular use of a slow,<br />
polymorphic function with a custom monomorhpic implementation.<br />
<br />
Consider:<br />
<haskell><br />
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]<br />
</haskell><br />
<br />
This is a bit slow, but useful. It's often used to zip ByteStrings into<br />
a new ByteString, that is:<br />
<haskell><br />
pack (zipWith f p q)<br />
</haskell><br />
<br />
We'd like to spot this, and throw away the intermediate [a] created. And<br />
also use a specialised implementation of:<br />
<haskell><br />
zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString<br />
</haskell><br />
<br />
We can use rules for this:<br />
<br />
<haskell><br />
"FPS specialise pack.zipWith" forall (f :: Word8 -> Word8 -> Word8) p q .<br />
pack (zipWith f p q) = zipWith' f p q<br />
</haskell><br />
<br />
This rule spots the specific use of zipWith we're looking for, and<br />
replaces it with a fast, specialised version.<br />
<br />
=== Rules and sections ===<br />
<br />
This is useful for higher order functions as well. As of ghc 6.6, the<br />
rule LHS syntax has been relaxed, allowing for sections and lambda<br />
abstractions to appear. Previously, only applications of the following<br />
form were valid:<br />
<br />
<haskell><br />
"FPS specialise break (x==)" forall x.<br />
break ((==) x) = breakByte x<br />
</haskell><br />
<br />
That is, replace occurences of: break (x==) with the optimised breakByte<br />
function. <br />
<br />
This code illustrates how higher order functions can be rewritten to<br />
optimised first order equivalents, for special cases like (==). In the<br />
case of Data.ByteString, functions using (==) or (/=) are much faster<br />
when implemented with memchr(3), and we can use rules to do this, as<br />
long as it is possible to match sections. In ghc 6.6 we can now write:<br />
<br />
<haskell><br />
"FPS specialise break (==x)" forall x.<br />
break (==x) = breakByte x<br />
<br />
"FPS specialise break (x==)" forall x.<br />
break (x==) = breakByte x<br />
</haskell><br />
<br />
Some fragility remains in this rule though, as described below.<br />
<br />
=== Literals, dictionaries and sections ===<br />
<br />
Consider:<br />
<haskell><br />
break (== 10)<br />
</haskell><br />
<br />
Hopefully, this can be rewritten to a "breakByte 10" call, however, the<br />
combination of sections, literals and dictionaries for Eq makes this<br />
rather fragile.<br />
<br />
The rule for break ends up translated by GHC as;<br />
<br />
<haskell><br />
forall ($dEq :: base:GHC.Base.Eq base:GHC.Word.Word8) <br />
(x :: base:GHC.Word.Word8)<br />
<br />
break (base:GHC.Base.== @ base:GHC.Word.Word8 $dEq x) = <br />
breakByte x<br />
</haskell><br />
<br />
Notice the LHS: an application of the selector to a (suitably-typed) Eq<br />
dictionary. GHC does very little simplification on LHSs, because if it<br />
does too much, the LHS doesn't look like you thought it did. Here it<br />
might perhaps be better to simplify to GHC.Word.Word8.==, by selecting<br />
from the dictionary, but GHC does not do that.<br />
<br />
When this rules works, GHC generates exactly that pattern; we get<br />
<br />
<haskell><br />
eq = (==) deq<br />
main = ... break (\x. eq x y) ...<br />
</haskell><br />
<br />
GHC is anxious about substituting eq inside the lambda, but it does it<br />
because (==) is just a record selector, and hence is very cheap. <br />
<br />
But when we put a literal inline, we get an (Eq a) constraint and a (Num<br />
a) constraint (from the literal). Ultimately, 'a' turns out to be Int,<br />
by defaulting, but we don't know that yet. So GHC picks the Eq<br />
dictionary from the Num dictionary:<br />
<br />
<haskell><br />
eq = (==) ($p1 dnum)<br />
main = ... break (\x. eq x y) ...<br />
</haskell><br />
<br />
Now the 'eq' doesn't look quite so cheap, and it isn't inlined, so the<br />
rule does not fire. However, GHC 6.6 has been modified to believe that<br />
nested selection is also cheap, so that makes the rule fire.<br />
<br />
The underlying lesson is this: the only robust way to make rules fire is<br />
if the LHS is a normal form. Otherwise GHC may miss the fleeting moment<br />
at which (an instance of) the rule LHS appears in the program. The way<br />
you ensure this is with inline phases: don't inline LHS stuff until<br />
later, so that the LHS stuff appears in the program more than<br />
fleetingly.<br />
<br />
But in this case you have (==) on the LHS, and you have no phase control<br />
there. So it gets inlined right away, so the rule doesn't match any<br />
more. The only way the rule "works" is because GHC catches the pattern<br />
right away, before (==) is inlined. Not very robust.<br />
<br />
To make this robust, you'd have to say something like<br />
<br />
<haskell><br />
instance Eq Word 8 where<br />
(==) = eqWord8<br />
<br />
eqWord8 = ..<br />
{-# NOINLINE [1] eqWord8 #-}<br />
<br />
{-# RULES<br />
"FPS specialise break (x==)" forall x.<br />
break (x`eqWord8`) = breakByte x<br />
#-}<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8969Concurrency demos/Zeta2006-12-08T11:31:13Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ fromIntegral n ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar $! zetaRange s range)<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
Replace the main function with:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
_ -> error "missing thread termination marker"<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
mapM_ (writeChan chan . Just) (zetaRange s range)<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Talk:Concurrency_demos/Zeta&diff=8782Talk:Concurrency demos/Zeta2006-11-29T19:45:43Z<p>Mux: </p>
<hr />
<div>Shouldn't<br />
<haskell><br />
forkIO (putMVar mvar (zetaRange s range))<br />
</haskell><br />
be<br />
<haskell><br />
forkIO (putMVar mvar $! zetaRange s range)<br />
</haskell><br />
[[User:Remi|Remi]]<br />
<br />
You're right, I've changed the code in the example, thanks!<br />
<br />
[[User:Mux|Mux]]</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8778Concurrency demos/Zeta2006-11-29T15:10:37Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ fromIntegral n ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar $! zetaRange s range)<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
Replace the main function with:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
mapM_ (writeChan chan . Just) (zetaRange s range)<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8777Concurrency demos/Zeta2006-11-29T14:33:14Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar $! zetaRange s range)<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
Replace the main function with:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
mapM_ (writeChan chan . Just) (zetaRange s range)<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Talk:Concurrency_demos/Zeta&diff=8776Talk:Concurrency demos/Zeta2006-11-29T14:01:13Z<p>Mux: </p>
<hr />
<div>Shouldn't<br />
<haskell><br />
forkIO (putMVar mvar (zetaRange s range))<br />
</haskell><br />
be<br />
<haskell><br />
forkIO (putMVar mvar $! zetaRange s range)<br />
</haskell><br />
[[User:Remi|Remi]]<br />
<br />
I'm not sure: using strict application could speed things up I guess, but it's not a correctness problem, is it?<br />
<br />
[[User:Mux|Mux]]</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8775Concurrency demos/Zeta2006-11-29T13:55:21Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
Replace the main function with:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
mapM_ (writeChan chan . Just) (zetaRange s range)<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8774Concurrency demos/Zeta2006-11-29T13:46:10Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
Replace the main function with:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
writeList2Chan chan (map Just (zetaRange s range))<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8773Concurrency demos/Zeta2006-11-29T13:43:54Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size')<br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= t = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
writeList2Chan chan (map Just (zetaRange s range))<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8772Concurrency demos/Zeta2006-11-29T13:40:59Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- mapM (thread s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
=== Or using Strategies ===<br />
Replace the <hask>Control.Concurrent...</hask> imports by<br />
<haskell><br />
import Control.Parallel.Strategies<br />
</haskell><br />
and replace main by<br />
<haskell><br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
let ranges = cut (1, n) t<br />
results = map (zetaRange s) ranges `using` parList rnf<br />
putStr $ unlines [ "Starting thread for range " ++ show r | r <- ranges ]<br />
print (sum (concat results))<br />
</haskell><br />
<br />
=== Using a Chan instead of MVars ===<br />
This isn't working yet...<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size')<br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
chan <- newChan<br />
terms <- getChanContents chan<br />
<br />
forM_ (cut (1,n) t) $ thread chan s<br />
<br />
let wait xs i result<br />
| i >= n = print result -- Done.<br />
| otherwise = case xs of<br />
Nothing : rest -> wait rest (i + 1) result<br />
Just x : rest -> wait rest i (result + x)<br />
<br />
wait terms 0 0<br />
where<br />
thread chan s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
forkIO $ do<br />
writeList2Chan chan (map Just (zetaRange s range))<br />
writeChan chan Nothing<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8745Concurrency demos/Zeta2006-11-28T21:39:03Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
-- Return the list of the terms of the zeta function for the given range.<br />
-- We don't sum the terms here but let the main thread sum the lists returned<br />
-- by all the other threads so as to avoid accumulating rounding imprecisions.<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> [a]<br />
zetaRange s (x,y) = [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum (concat results))<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8744Concurrency demos/Zeta2006-11-28T21:17:40Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> a<br />
zetaRange s (x,y) = sum [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8743Concurrency demos/Zeta2006-11-28T21:15:33Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> a<br />
zetaRange s (x,y) = sum [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8742Concurrency demos/Zeta2006-11-28T21:14:15Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
<br />
zetaRange :: (Floating a, Integral b) => a -> (b, b) -> a<br />
zetaRange s (x,y) = sum [ (fromIntegral n) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8726Concurrency demos/Zeta2006-11-28T15:22:37Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8725Concurrency demos2006-11-28T15:22:22Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
[http://haskell.org/haskellwiki/Concurrency/Zeta Riemann's Zeta function approximation]</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8724Concurrency demos2006-11-28T15:22:00Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
[http://haskell.org/haskellwiki/GHC/Concurrency/Zeta Riemann's Zeta function approximation]</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8723Concurrency demos/Zeta2006-11-28T15:20:53Z<p>Mux: </p>
<hr />
<div>__TOC__<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell><br />
<br />
== Benchmarks ==<br />
<br />
Insert benchmarks here! :-)</div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos/Zeta&diff=8722Concurrency demos/Zeta2006-11-28T15:19:21Z<p>Mux: </p>
<hr />
<div>== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8721Concurrency demos2006-11-28T13:58:38Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8720Concurrency demos2006-11-28T13:56:50Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8719Concurrency demos2006-11-28T13:56:31Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8718Concurrency demos2006-11-28T13:54:59Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8717Concurrency demos2006-11-28T13:53:42Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating (Complex a), RealFloat a, Integral b) => Complex a -> (b, b) -> Complex a<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print (sum results)<br />
where<br />
thread s range = do<br />
putStrLn ("Starting thread for range " ++ show range)<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8716Concurrency demos2006-11-28T13:51:57Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating (Complex a), RealFloat a, Integral b) => Complex a -> (b, b) -> Complex a<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n = (x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print $ sum results<br />
where<br />
thread s range = do<br />
putStrLn $ "Starting thread for range " ++ show range<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8715Concurrency demos2006-11-28T13:51:03Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating (Complex a), RealFloat a, Integral b) => Complex a -> (b, b) -> Complex a<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n =<br />
(x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print $ sum results<br />
where<br />
thread s range = do<br />
putStrLn $ "Starting thread for range " ++ show range<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8714Concurrency demos2006-11-28T13:45:44Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
This little piece of code computes an approximation of Riemann's zeta function, balancing the work to be done between N threads.<br />
<br />
<haskell><br />
module Main where<br />
<br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating (Complex a), RealFloat a, Integral b) =><br />
Complex a -> (b, b) -> Complex a<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n =<br />
(x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print $ sum results<br />
where<br />
thread s range = do<br />
putStrLn $ "Starting thread for range " ++ show range<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Muxhttps://wiki.haskell.org/index.php?title=Concurrency_demos&diff=8713Concurrency demos2006-11-28T13:44:27Z<p>Mux: </p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Code]]<br />
<br />
A large range of small demonstration programs for using concurrent and<br />
parallel Haskell are in the Haskell [http://darcs.haskell.org/testsuite/tests/ghc-regress/concurrent/should_run/ concurrency regression tests]. In particular, they show the use of <hask>MVars</hask> and <hask>forkIO</hask>.<br />
<br />
== A simple example of parallelism in Haskell ==<br />
<br />
<haskell><br />
module Main where<br />
<br />
import Control.Concurrent<br />
import Control.Concurrent.MVar<br />
import Control.Monad<br />
import Data.Complex<br />
import System.Environment<br />
<br />
zetaRange :: (Floating (Complex a), RealFloat a, Integral b) =><br />
Complex a -> (b, b) -> Complex a<br />
zetaRange s (x,y) = sum [ (fromIntegral n :+ 0) ** (-s) | n <- [x..y] ]<br />
<br />
cut :: (Integral a) => (a, a) -> a -> [(a, a)]<br />
cut (x,y) n =<br />
(x, x + mine - 1) : cut' (x + mine) size (y - mine)<br />
where<br />
(size, modulo) = y `divMod` n<br />
mine = size + modulo<br />
<br />
cut' _ _ 0 = []<br />
cut' x' size' n' = (x', x' + size' - 1) : cut' (x' + size') size' (n' - size') <br />
<br />
getParams :: IO (Int, Int, Complex Double)<br />
getParams = do<br />
argv <- getArgs<br />
case argv of<br />
(t:n:s:[]) -> return (read t, read n, read s)<br />
_ -> error "usage: zeta <nthreads> <boundary> <s>"<br />
<br />
main :: IO ()<br />
main = do<br />
(t, n, s) <- getParams<br />
childs <- zipWithM thread (repeat s) (cut (1, n) t)<br />
results <- mapM takeMVar childs<br />
print $ sum results<br />
where<br />
thread s range = do<br />
putStrLn $ "Starting thread for range " ++ show range<br />
mvar <- newEmptyMVar<br />
forkIO (putMVar mvar (zetaRange s range))<br />
return mvar<br />
</haskell></div>Mux