【问题标题】:Why do we need 'seq' or 'pseq' with 'par' in Haskell?为什么我们在 Haskell 中需要 'seq' 或 'pseq' 和 'par'?
【发布时间】:2011-06-02 09:09:11
【问题描述】:

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

a `par` b `pseq` a+b

为什么以下内容还不够?

a `par` b `par` a+b

上面的表达式看起来很有描述性:尝试并行计算ab,并返回结果a+b。只是效率的原因:第二个版本会触发两次而不是一次?

下面更简洁的版本怎么样?

a `par` a+b

为什么我们需要确保在a+b 之前评估b,就像在原始标准代码中一样?

【问题讨论】:

    标签: haskell parallel-processing speculative-execution


    【解决方案1】:

    好的。我认为以下论文回答了我的问题:http://community.haskell.org/~simonmar/papers/threadscope.pdf

    总之,问题与

    a `par` b `par` a+b 
    

    a `par` a+b
    

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

    原版

    a `par` b `pseq` a+b
    

    确保主线程在b 之前 a+b 上工作(否则将开始评估a),从而使火花a 有机会具体化为用于并行评估的线程。

    【讨论】:

    • 这是正确的,也解释了为什么seq不足以解决这个问题。 seq 不保证评估的顺序。在seq b (a+b) 中,只要在评估(a+b)b 在WHNF 中,主线程就可以在b 之前评估a
    • 我看不出该论点如何描述par a (par b (a + b)) 的问题 - 当然,ab 将立即被评估,并且相应的火花会消失,但另一个火花应该非常活跃,产生并行性。当然,创建火花然后熄灭火花可能不是最有效的方法,但它可以工作并将评估顺序问题留给编译器。
    • par a (a + b) 的情况下,如果运行时首先选择b,仍然可以获得“幸运”并行化。然后a spark 不会失败。 PDF中提到了这一点:community.haskell.org/~simonmar/papers/threadscope.pdf(第2页)
    【解决方案2】:
    a `par` b `par` a+b 
    

    将并行计算 a 和 b 并返回 a+b,是的。

    但是,那里的 pseq 确保a+b 之前评估 a 和 b。

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

    【讨论】:

      【解决方案3】:

      a `par` b `par` a+b 会为ab 创建火花,但会立即到达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 火花有机会在我们尝试评估a+b 之前实现,并且我们没有创建任何不必要的火花。

      【讨论】:

        猜你喜欢
        • 2012-01-24
        • 1970-01-01
        • 2019-06-09
        • 2020-09-05
        • 2012-12-03
        • 2016-06-25
        • 2017-03-12
        • 1970-01-01
        • 2018-12-09
        相关资源
        最近更新 更多