Haskell PAR函数的逻辑基础
Haskell PAR函数的逻辑基础,haskell,parallel-processing,Haskell,Parallel Processing,par功能是如何工作的?其签名为: par :: a -> b -> b. 但这很奇怪。为什么不是: par::(a->b)->a->b (获取函数,在新线程中执行并返回结果) 另一个问题,这是正常的haskell多线程吗 par用于推测并行性,依赖于惰性 您推测未计算的a应该在您忙于处理b时计算 稍后在您的程序中,您可能会再次引用a,它将准备就绪 这里有一个例子。我们希望将3个数字相加。每个数字的计算都很昂贵。我们可以并行计算它们,然后将它们相加: main = a `par`
par
功能是如何工作的?其签名为:
par :: a -> b -> b.
但这很奇怪。为什么不是:
par::(a->b)->a->b
(获取函数,在新线程中执行并返回结果)
另一个问题,这是正常的haskell多线程吗
par
用于推测并行性,依赖于惰性
您推测未计算的a
应该在您忙于处理b
时计算
稍后在您的程序中,您可能会再次引用a
,它将准备就绪
这里有一个例子。我们希望将3个数字相加。每个数字的计算都很昂贵。我们可以并行计算它们,然后将它们相加:
main = a `par` b `par` c `pseq` print (a + b + c)
where
a = ack 3 10
b = fac 42
c = fib 34
fac 0 = 1
fac n = n * fac (n-1)
ack 0 n = n+1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1))
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
因为我们在Haskell中不“执行函数”。我们评估值,这就是我们控制处理器活动的方式。基本上,parxy
所做的是:在评估结果y
时,运行时也将预先评估x
,尽管这本身还没有要求
请注意,这不一定是现在编写并行代码的最佳方式。看看新的替代品,比如。您可能需要阅读。除了前面的答案之外,值得指出的是,
a
和b
将仅评估为弱头范式(WHNF)(即应用最外层的约化或构造函数),因此使用deepseq
强制评估可能很有用
就操作语义而言,par
创建一个spark,它是指向thunk(未计算)的指针,并添加到spark池中。这是非常便宜的,可能有数百万的火花。线程创建是建议性的,运行时系统可以决定不将a
转换为线程,并通过忽略spark或将子spark包含在父线程中来修剪多余的并行性
您显示的图片可能表明您的代码存在问题,在CPU2上执行的线程要做的工作量明显减少(负载不平衡)。它的有效用法是什么?:一个B=PAR(a^ 4)(复制(a^ 4)b)@ Serah,这两个原因是无用的:(1)在两个副本之间没有保证共享:<代码> A^ 4 < /代码>,所以评估其中一个对另一个没有帮助(GHC可能决定共享它们,我不确定。)(2)
replicate
函数要做的第一件事就是计算它的第一个参数,这样就没有时间让它被par
预先估值了。。。你能用PAR函数写一些好的例子吗?这样写是正确的吗?代码=乐趣=PAR A.PAR B.PAR C$(A+B+C),其中A=ACK 3 10;b=fac 42;c=fib 34@Seraph这更好,因为这些计算更昂贵。还有一个格式提示:要在SO中获得a`par`b`par`c`par`a+b+c
,请在整个代码周围使用双反引号。