我正在通过{Haskell中的并行和并发编程的Chapter 3工作,它有以下使用策略并行运行fibonacci序列的示例:
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')
-- >>
当我用以下代码编译时:
ghc -O2 strat.hs -threaded -rtsopts -eventlog
并以1核
运行它./strat +RTS -N1 -s -l
我得到以下时间输出:
Total time 1.23s ( 1.24s elapsed)
使用两个核心./strat +RTS -N2 -s -l
Total time 1.47s ( 1.46s elapsed)
当我使用threadscope检查日志时,很容易看到只有1个核心用于运行haskell代码而第二个核心是gc整个时间。
我认为这可能是因为在调用打印导致计算没有并行发生之前,对fib
的每个函数调用的评估实际上并未发生。我对原始代码做了一些修改:
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')
然而这并没有帮助。我在这里缺少什么,为什么这个计算不是并行发生的?