I'm working through Chapter 3 of "Parallel and Concurrent Programming in Haskell" and it has the following example of running the fibonacci sequence in parallel using strategies:
import Control.Parallel
import Control.Parallel.Strategies (rpar, Strategy, using)
import Text.Printf
import System.Environment
-- <<fib
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
-- >>
main = print pair
where
pair =
-- <<pair
(fib 35, fib 36) `using` parPair
-- >>
-- <<parPair
parPair :: Strategy (a,b)
parPair (a,b) = do
a' <- rpar a
b' <- rpar b
return (a',b')
-- >>
when I compile this with:
ghc -O2 strat.hs -threaded -rtsopts -eventlog
and run it with 1 core
./strat +RTS -N1 -s -l
I get the following time output:
Total time 1.23s ( 1.24s elapsed)
With two cores ./strat +RTS -N2 -s -l
Total time 1.47s ( 1.46s elapsed)
When I inspect the log with threadscope, It's easy to see that only 1 core is ever being used to run haskell code and the 2nd core is gc'ing the entire time.
I thought this might be because the evaluation of each function call to to fib
wasn't actually occurring until the call the print resulting in the computing not happening in parallel. I made a slight modification to the original code:
import Control.DeepSeq(force, NFData)
parPair :: (NFData a, NFData b) => Strategy (a,b)
parPair (a,b) = do
a' <- rpar $ force a
b' <- rpar $ force b
return (a',b')
However this didn't help. What am I missing here, Why is this computation not occurring in parallel?