了解Eval Monad的`rpar`

时间:2015-06-18 12:58:58

标签: haskell

查看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 36fib 35

调用fib ...时是否会发生实际工作,即计算函数(runEval test)?或者可能需要evaluate ...?或者,最后,也许在调用print r来完全评估它时会计算出来吗?

我不清楚何时rpar执行实际工作。

1 个答案:

答案 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 rx完成评估。

理论上,以下代码应强制y等到test1x完成评估后再返回。

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}的评估},但是xy 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次调用,您就会知道Donerseq已经开始被评估但不能保证已经完成,但是通过这些调用,您知道x在调用y之前,还会对{}和x进行评估。