Haskell 为什么我们需要';seq';或';pseq';与';par';在哈斯克尔?

Haskell 为什么我们需要';seq';或';pseq';与';par';在哈斯克尔?,haskell,parallel-processing,speculative-execution,Haskell,Parallel Processing,Speculative Execution,我试图理解为什么我们需要标准示例代码的所有部分: a `par` b `pseq` a+b 为什么下面的内容还不够 a `par` b `par` a+b 上面的表达式似乎非常具有描述性:尝试并行计算a和b,并返回结果a+b。这仅仅是因为效率:第二个版本会触发两次而不是一次 下面这个更简洁的版本怎么样 a `par` a+b 为什么我们需要确保在a+b之前对b进行评估,就像原始的标准代码一样 a `par` b `par` a+b 将并行计算a和b,并返回a+b,是 但是,那里的pse

我试图理解为什么我们需要标准示例代码的所有部分:

a `par` b `pseq` a+b
为什么下面的内容还不够

a `par` b `par` a+b
上面的表达式似乎非常具有描述性:尝试并行计算
a
b
,并返回结果
a+b
。这仅仅是因为效率:第二个版本会触发两次而不是一次

下面这个更简洁的版本怎么样

a `par` a+b
为什么我们需要确保在
a+b
之前对
b
进行评估,就像原始的标准代码一样

a `par` b `par` a+b 
将并行计算a和b,并返回a+b,是

但是,那里的pseq确保在a+b之前对a和b进行评估


有关该主题的更多详细信息,请参阅。

确定。我认为以下论文回答了我的问题:

总之,问题在于

a `par` b `par` a+b 

缺乏评价的有序性。在这两个版本中,主线程立即开始处理
a
(或者有时处理
b
),导致火花立即“熄灭”,因为不再需要启动线程来评估主线程已经开始评估的内容

原版

a `par` b `pseq` a+b

确保主线程在
a+b
a+b
之前在
b
上工作(否则将开始计算
a
),这样就给了火花
a
具体化为并行计算线程的机会。

a`par`b`par`a+b
a
b
创建火花,但是
a+b
立即到达,因此其中一个火花将熄灭(即,它在主线程中进行计算)。问题在于效率,因为我们制造了不必要的火花。如果您使用它来实现并行分治,那么开销将限制您的加速比

a`par`a+b
似乎更好,因为它只会产生一个火花。但是,在
b
之前尝试评估
a
会使
a
的火花熄灭,而
b
没有火花,这将导致
a+b
的顺序评估。将顺序切换到
b+a
可以解决此问题,但作为代码,这不会强制执行顺序,Haskell仍然可以将其评估为
a+b


因此,在尝试计算
a+b
之前,我们在主线程中执行
a`par`b`pseq`a+b
以强制计算
b
。在我们尝试评估
a+b
之前,这给了
a
火花出现的机会,我们没有产生任何不必要的火花。

这是正确的,也解释了为什么
seq
不足以解决此问题
seq
不保证评估顺序。在
seq b(a+b)
中,主线程可以在
b
之前计算
a
,只要
b
(a+b)
进行计算时处于WHNF中。我不知道该参数如何描述
para(parb(a+b))
的问题-当然,会立即计算
a
b
,相应的火花会熄灭,但另一个火花应该非常活跃,产生平行性。当然,创建然后熄灭火花可能不是实现这一点的最有效方法,但它是有效的,并将计算顺序问题留给编译器。在
para(a+b)
的情况下,如果运行时选择
b
,仍然有可能获得“幸运的”并行化。然后
a
火花就不会熄灭。PDF:community.haskell.org/~simonmar/papers/threadscope.PDF(第2页)中提到了这一点
a `par` b `pseq` a+b