[Haskell-cafe] forkIO on multicore[MESSAGE NOT SCANNED]

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Thu Dec 25 18:33:36 EST 2008

On Tue, 2008-12-23 at 18:27 +0000, Paul Keir wrote:
> Hi Duncan,
> I'm following the story regarding (parallel) GC in this example
> with interest, but forgive me if I ask a more minor question
> regarding your modification of an extra parameter, "n", to
> "heavytask". Does this really help (to ensure that each core
> does work independently)? Surely, with fibs now described in a
> where clause, the "0:1:etc." form would not be shared among the
> (8) instantiations of "heavytask"?

Yes, that was the purpose of the modification, to ensure that the value
was not shared but calculated independently. I wanted to test speedup
with a trivially parallel workload.

If the value really is shared then there will necessarily be no speedup.
That is because the definition of this value does not use any explicit
parallelism and ghc does not do any automatic parallelisation. Demanding
the same evaluation from multiple threads just causes the other threads
to block awaiting evaluation.

> > heavytask m n = putMVar m $! (fibs !! 100000)
> >   where
> >     fibs = n : (n+1) : zipWith (+) fibs (tail fibs)

To get parallel speedup when evaluating a single value like this we need
a different definition. We could use IO threads with forkIO and explicit
shared variables or message passing. However since this is a pure
function a much nicer approach is to use a pure implementation using the
`par` operator:


-- parallel version of the code with thresholding
parfib :: Int -> Int -> Int
parfib n t | n <= t = nfib n
           | otherwise = n1 `par` (n2 `pseq` n1 + n2 + 1)
                         where n1 = parfib (n-1) t
                               n2 = parfib (n-2) t

Using `par` creates "sparks" which are even lighter weight than Haskell
IO threads. They are just values/thunks and get evaluated by a pool of
ordinary Haskell threads.


More information about the Haskell-Cafe mailing list