【问题标题】:How to evaluate tuples in parallel using rpar Strategy in Haskell?如何在 Haskell 中使用 rpar 策略并行评估元组?
【发布时间】:2012-11-12 08:35:48
【问题描述】:

我在 Haskell 中偶然发现了 Eval monad 和 rpar Strategy 的问题。考虑以下代码:

module Main where

import Control.Parallel.Strategies

main :: IO ()
main = print . sum . inParallel2 $ [1..10000]

inParallel :: [Double] -> [Double]
inParallel xss = runEval . go $ xss
    where
      go []  = return []
      go (x:xs) = do
        x'  <- rpar $ x + 1
        xs' <- go xs
        return (x':xs')

inParallel2 :: [Double] -> [Double]
inParallel2 xss = runEval . go $ xss
    where
      go []  = return []
      go [x] = return $ [x + 1]
      go (x:y:xs) = do
        (x',y') <- rpar $ (x + 1, y + 1)
        xs'     <- go xs
        return (x':y':xs'

我是这样编译和运行的:

ghc -O2 -Wall -threaded -rtsopts -fforce-recomp -eventlog eval.hs
./eval +RTS -N3 -ls -s

当我使用inParallel 时,函数并行性按预期工作。在输出运行时统计中我看到:

SPARKS: 100000 (100000 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

当我切换到inParallel2 函数时,所有并行性都消失了:

SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

为什么元组的求值不能并行工作?在将元组传递给 rpar 之前,我尝试强制执行该元组:

rpar $!! (x + 1, y + 1)

但仍然没有结果。我做错了什么?

【问题讨论】:

    标签: haskell parallel-processing


    【解决方案1】:

    rpar 策略注释了一个可能并行计算的术语,但仅限于 弱头范式,这实质上意味着直到最外层的构造函数。所以对于一个整数或双精度数,这意味着完全评估,但对于一对,只有对构造函数,而不是它的组件,会被评估。

    在将它传递给rpar 之前强制它不会有帮助。现在,您在本地评估该对,然后再注释已评估的元组以进行可能的并行评估。

    您可能希望将rparrdeepseq 策略结合起来,从而声明应该完全评估该术语,如果可能的话并行。你可以这样说

    (rpar `dot` rdeepseq) (x + 1, y + 1)
    

    dot 运算符用于组合策略。

    但是,您的代码还有另一个问题:模式匹配强制立即评估,因此对rpar-annotated 表达式使用模式匹配通常是一个坏主意。特别是行

    (x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1)
    

    将破坏所有并行性,因为在另一个线程可以拾取火花进行评估之前,本地线程已经开始评估它以匹配模式。您可以通过使用惰性/无可辩驳的模式来防止这种情况:

    ~(x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1)
    

    或者使用fstsnd 访问该对的组件。

    最后,如果您创建的火花与将整数加一一样便宜,则不要指望实际的加速。虽然 spark 本身相对便宜,但它们并非免费,因此如果您为并行评估注释的计算成本较高,它们会更好地工作。

    您可能想阅读一些有关使用策略的教程,例如 Simon Marlow 的 Parallel and Concurrent Programming using Haskell 或我自己的Deterministic Parallel Programming in Haskell

    【讨论】:

    • 谢谢!这个问题实际上是在我阅读 Marlow 的教程并自己做一些练习时出现的。添加 1 只是一个示例,我不想通过一些复杂的计算使示例代码复杂化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多