这段代码如何:
parfib :: Int -> Int
parfib 0 = 1
parfib 1 = 1
parfib n = nf2 `par` (nf1 `par` (nf1+nf2+1))
where nf1 = parfib (n-1)
nf2 = parfib (n-2)
比这更好的是:
parfib :: Int -> Int
parfib 0 = 1
parfib 1 = 1
parfib n = nf2 `par` (nf1 `seq` (nf1+nf2+1))
where nf1 = parfib (n-1)
nf2 = parfib (n-2)
我没有在网上找到的解释说“为了确保以正确的顺序对主表达式求值(即在不阻塞子任务的主任务的情况下,使用seq注释)”。
为什么使用seq?我知道这会迫使解释器首先评估parfib(n-1),但为什么有必要呢?
当执行第二个程序时,交互程序是否会在并行评估nf1 + nf2 + 1表达式的nf1时引发一个新的过程来评估nf2?有什么需要告诉它指定它应该以nf1开头?
最佳答案
与nf1
并行评估nf1+...
并没有多大意义,因为后者依赖于nf1,因此它所要做的只是阻塞nf1
的 Spark 。使用seq
,只有在知道它已经被评估后,它才会尝试使用nf1
。
关于multithreading - 对并行Haskell感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/713150/