查看Parallel and Concurrent Programming in Haskell中的以下示例:
main = do
[n] <- getArgs
let test = [test1,test2,test3,test4] !! (read n - 1)
t0 <- getCurrentTime
r <- evaluate (runEval test)
printTimeSince t0
print r
printTimeSince t0
test1 = do
x <- rpar (fib 36)
y <- rpar (fib 35)
return (x,y)
这本书展示了它的编译:
$ ghc -O2 rpar.hs -threaded
然后运行上述测试:
$ ./rpar 1 +RTS -N2
time: 0.00s
(24157817,14930352)
time: 0.83s
如果我理解正确,Eval Monad(使用rpar
)会同时计算fib 36
和fib 35
。
调用fib ...
时是否会发生实际工作,即计算函数(runEval test)
?或者可能需要evaluate ...
?或者,最后,也许在调用print r
来完全评估它时会计算出来吗?
我不清楚何时为rpar
执行实际工作。
答案 0 :(得分:5)
这是我的猜测,但我似乎无法在我的笔记本电脑上复制这个内容,我需要从cabal获取太多的进口货。
test1 = do
x <- rpar (fib 36)
y <- rpar (fib 35)
return (x,y)
在此,您同时激发对(fib 36)
和(fib 35)
的评价,但您不会等待它们 - 您只需立即返回(x,y)
,而{{1 }}和x
仍在评估中。然后,我们到达y
,您将被迫等到print r
和x
完成评估。
理论上,以下代码应强制y
等到test1
和x
完成评估后再返回。
y
然后,运行它应该给你大概
test1 = do
x <- rpar (fib 36)
y <- rpar (fib 35)
rseq x
rseq y
return (x,y)
...希望
最后回到我的机器,复制了条件,我建议的代码给出了预期的结果。然而,OP提出了另一个好问题:如果$ ./rpar 1 +RTS -N2
time: 0.83s
(24157817,14930352)
time: 0.83s
仅评估为WHNF,为什么它甚至会在调用print之前完成工作?
答案在evaluate
的{{3}}中 - 换句话说,它不是Control.Parallel.Strategies
推动对evaluate
和{{1}的评估},但是x
。 y
monad在第一个参数中是严格的:在runEval
中,它将评估Eval
(请在继续之前查看monad definition)。然后,脱糖x >>= f
给出:
x
然后,因为test1
只有&#34;火花&#34;评估时,它使用this question(它开始评估第一个参数但立即返回第二个参数)并立即返回test1 = (rpar (fib 36)) >>= (\x ->
(rpar (fib 35)) >>= (\y ->
(rseq x) >>= (\_ ->
(rseq y) >>= (\_ ->
return (x,y)))))
,但是,par
(如rpar
,但严格只有在第一个参数中)才会返回Done
,直到它的参数被实际评估(到WHNF)。因此,如果没有seq
次调用,您就会知道Done
和rseq
已经开始被评估但不能保证已经完成,但是通过这些调用,您知道x
在调用y
之前,还会对{}和x
进行评估。