haskell - 控制并行执行

标签 haskell parallel-processing

Haskell 提供了一个 par组合器,它将“ Spark ”排队,以便与当前线程并行进行可能的评估。它还提供了 pseq组合器,它强制纯代码的评估以特定顺序发生。

Haskell 似乎没有提供一种产生多个 Spark 然后等待它们全部完成的方法。使用显式并发实现这一点非常简单,但使用纯 Spark 似乎是不可能的。

在某种程度上,这可能是因为 Spark 的预期用例。它们似乎是为推测性评估而设计的。也就是说,做可能需要但可能不需要的工作。因此, Spark 仅在空闲的核心上运行。

但是,这不是我的用例。我有一堆我知道的结果,事实上,很快就会需要这些结果。如果我在 Spark 点燃之前开始尝试处理结果,我将再次以一堆失败的 Spark 结束单线程。

当然,par等待 Spark 完成,它不会实现任何并行性!但是,如果有某种方法可以产生多个 Spark 然后等待它们全部完成,那将非常有用。我找不到任何方法来做到这一点。

有人有什么有用的建议吗? (显然,除了“使用显式并发”。)

最佳答案

真正简短的答案

你不能。

简短的回答

要等待 Spark 完成,请尝试评估 Spark 正在评估的内容。例如,如果您有表达式 ab , 计算 a + b , 你可以做

a `par` b `par` (a + b)

或者
a `par` b `pseq` (a + b)

长答案

当您使用 par 创建 Spark 时,你是在告诉运行时系统“我稍后会需要这个值,所以你应该并行评估它。”当您稍后需要该值时, Spark 已经评估了表达式,或者没有。如果有,thunk 将被一个值替换,因此重新评估没有成本 - 它只是获取值。如果它没有被评估为 Spark ,那么等待 Spark 是没有用的——它可能需要一段时间才能被安排,而线程等待是在浪费时间。您应该自己评估表达式,而不是等待。本质上,无需等待 Spark 。您只需尝试评估原始表达式并获得性能优势。

另外,关于投机的说明 - 虽然 Spark 可以并且经常用于投机,但这并不完全是它们的设计目的。我看到了par用于简单的并行化,如 pfib下面,比我看到它用于猜测的次数要多得多。

示例

一个标准的例子是并行化斐波那契数,从串行
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

到平行
pfib 0 = 0
pfib 1 = 1
pfib n = l `par` r `pseq` (l + r) where
    l = pfib (n - 1)
    r = pfib (n - 2)

.

现在举一个使用推测的例子:
spec :: a -- a guess to the input value
    -> (a -> b) -- a function to tranform the input value
    -> a -- the actual input value - this will require computation
    -> b -- the function applied to the input value
spec guess f input = let speculation = f guess in speculation `par`
    if guess == input
        then speculation
        else f input

我得到这个的hackage包,speculation ,实际上有一些优化,例如不在单个内核上执行此操作并检查输入是否已被评估,但这与函数的工作无关。

使事情更明确的其他解决方案
  • monad-par
  • Strategies , 它利用 par .
  • 与 IO 混为一谈。这里有很多东西。
  • 关于haskell - 控制并行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11828654/

    相关文章:

    matlab - 并行运行 MEX 文件时出现段错误

    haskell - Parallel Haskell - GHC GC'ing sparks

    haskell - 未找到堆栈初始化包

    debugging - 在 GHCi 调试器中中断并继续,而不使用断点

    haskell - 在 Haskell 中导出任意函数

    string - 通过在 Haskell 中插入每个后缀来构建后缀树

    haskell - 为 (' :) 派生一个 Typeable 实例

    c++ - 异步代理库和数据共享

    multithreading - 多核 CPU 上能否真正同时执行 2 条指令

    multithreading - Valgrind 处理线程和机器级同步指令的效果如何?