【问题标题】:Haskell parallel computation using an STArray使用 STArray 的 Haskell 并行计算
【发布时间】:2012-04-09 20:52:38
【问题描述】:

我正在尝试并行计算,并将结果写入 STArray。我认为这段代码显示了我正在尝试做的事情。但是,我遇到了编译错误。

import Control.Monad
import Control.Monad.ST
import Control.Parallel
import Data.Array.ST

main = do
    arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
    runSTArray $ do
        par (writeArray arr (1,1) 17) (writeArray arr (2,2) 23)
        return arr
    print arr

我应该怎么做?

【问题讨论】:

  • 我认为您应该使用Repa 进行并行数组操作。

标签: arrays haskell parallel-processing monads state-monad


【解决方案1】:

您使用newArray,其类型为ST s (STArray s (Int, Int) Int)。但是,您在main 函数的主体中使用它,这意味着您do 的所有内容都必须具有IO 类型。 ST 不是IO,所以类型不能匹配。

您应该首先将newArray 移动到可以访问ST monad 的上下文中。这个上下文当然在runSTArray的正文中是可用的,所以把正文改成:

    runSTArray $ do
        arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
        par (writeArray arr (1,1) 17) (writeArray arr (2,2) 23)
        return arr

然后,您需要重新考虑 par 的行为方式。 par 用于创建并行计算,不能用于单子操作; monad 通常根本无法并行化。特别是,ST monad 甚至没有为并行计算提供任何替代方案。由于对数组的并行写入可能会导致竞争条件(如果覆盖同一个单元会发生什么情况?哪个写入会计数,哪个不会?),在这里允许并行是不安全的。您必须按顺序更改数组:

    runSTArray $ do
        arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
        writeArray arr (1,1) 17
        writeArray arr (2,2) 23
        return arr

但是,写入并不昂贵;可能是昂贵的值的计算。假设您要即时计算1723;然后您可以执行以下操作:

let a = someLongCalculation 12534
    b = a `par` (someLongCalculation 24889)
writeArray arr (1, 1) a
writeArray arr (2, 2) b

最后,你必须意识到runSTArray返回结果数组,所以你必须像这样存储它:

import Control.Monad
import Control.Monad.ST
import Control.Parallel
import Data.Array.ST

main =
  let pureArr =
        runSTArray $ do
          arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
          writeArray arr (1,1) 17
          writeArray arr (2,2) 23
          return arr
  in print pureArr

我认为STArrays 在这里不是正确的解决方案。在需要并行对称数组计算的情况下,您应该使用更强大的数组库,例如 repa

【讨论】:

  • 谢谢,我已经知道如何进行顺序读写了。看起来我被卡住了,因为正如你所指出的,par monad 不允许我并行化这些动作。我将不得不研究如何使用 Repa 实现对数组的并行写入。
  • ST monad 不允许您进行并行处理。不过,如果您愿意,可以在 IOforkIO 和公司中进行。
  • @LouisWasserman 你能详细说明一下吗?这是否允许我从所有分叉线程写入同一个数组?
  • Mutable arrays 同时存在于STIO,因此如果您不希望ST 提供的类型保证,您可以从IO 使用它们。另外,当涉及到可变数组的并行修改时,请注意赛车。
  • 是的。您可以并行写入 IO 数组,但如果多个线程尝试写入或读取 same 数组条目,线程安全将直接消失。
【解决方案2】:

par 用于并行组合纯操作。您正在编写有效的操作。你不能使用标准杆。此外,并行性一种效果(至少在与突变组合时),并且在 ST monad 中对您不可用。我不能就构建代码的正确方法给你建议,因为事情太精简了,看不出你的实际问题域是什么。然而,我的一般建议是,使用像 fork(在 IO monad 中) 之类的显式并发构造来使用纯操作而不是 mutatey 数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多