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
,请在整个代码周围使用双反引号。