为什么我们在Haskell中需要'seq'或'pseq'和'par'?

kir*_*kun 30 parallel-processing haskell speculative-execution

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

a `par` b `pseq` a+b
Run Code Online (Sandbox Code Playgroud)

以下为什么不够?

a `par` b `par` a+b
Run Code Online (Sandbox Code Playgroud)

上述表达式似乎很描述:尝试同时评估ab并行,并返回结果a+b.仅仅是效率的原因:第二个版本会引发两次而不是一次?

以下,更简洁的版本怎么样?

a `par` a+b
Run Code Online (Sandbox Code Playgroud)

为什么我们需要确保在原始标准代码b之前进行评估a+b

kir*_*kun 30

好.我想以下文章回答了我的问题:http://community.haskell.org/~simonmar/papers/threadscope.pdf

总之,问题所在

a `par` b `par` a+b 
Run Code Online (Sandbox Code Playgroud)

a `par` a+b
Run Code Online (Sandbox Code Playgroud)

是缺乏评估的顺序.在这两个版本中,主线程立即a(或有时b)立即工作,导致火花立即"消失",因为不再需要启动线程来评估主线程已经开始评估的内容.

原始版本

a `par` b `pseq` a+b
Run Code Online (Sandbox Code Playgroud)

确保主线程在b 之前工作 a+b(否则就会开始评估a),从而使spark有机会a实现并行评估的线程.

  • 这是正确的,也解释了为什么`seq`不足以解决这个问题.`seq`不保证评估的顺序.在`seq b(a + b)`中,只要`b`在WHNF中,当评估`(a + b)`时,主线程可以在'b'之前评估`a`. (6认同)
  • 我没有看到这个论点如何用'par a(par b(a + b))来描述问题` - 确定,`a`或`b`将立即被评估,并且相应的火花会失败,但是其他火花应该非常活跃,产生平行性.当然,创建然后失败的火花可能不是最有效的方法,但它起作用并将评估顺序问题留给编译器. (2认同)

Alp*_*ari 16

a `par` b `par` a+b 
Run Code Online (Sandbox Code Playgroud)

将并行评估a和b并返回a + b,是的.

然而,PSEQ确保前A和B两者进行评估A + B是.

有关主题的更多详细信息,请参阅此链接.


Mat*_*att 6

a `par` b `par` a+b两者产生火花ab,但a+b被立即达到这样的火花的人会以失败告终(即,它在主线程中进行评估).问题在于效率,因为我们创造了不必要的火花.如果您使用它来实现并行分而治之,则开销将限制您的加速.

a `par` a+b似乎更好,因为它只会产生一个火花.然而,试图评估a之前b将失去火花a,并且由于b没有火花,这将导致顺序评估a+b.切换顺序b+a将解决此问题,但作为代码,这不会强制执行排序,Haskell仍然可以将其评估为a+b.

因此,我们在尝试评估之前a `par` b `pseq` a+b强制b在主线程中进行评估a+b.a在我们尝试评估之前,这给了实现的机会a+b,并且我们没有创造任何不必要的火花.