haskell - 使用 repa 时将 Identity monad 与 mmultP 一起使用有什么问题?

标签 haskell parallel-processing repa

我不明白为什么这个程序使用 repa :

import Data.Array.Repa
import Data.Array.Repa.Algorithms.Matrix
import Data.Functor.Identity

go = runIdentity $ do
  let mat = fromListUnboxed (ix2 2 2) [1..4]
  let ins = fromListUnboxed (ix2 2 1) [1, 1]
  mmultP mat ins

给我以下警告:

Data.Array.Repa: Performing nested parallel computation sequentially.
  You've probably called the 'compute' or 'copy' function while another
  instance was already running. This can happen if the second version
  was suspended due to lazy evaluation. Use 'deepSeqArray' to ensure
  that each array is fully evaluated before you 'compute' the next one.

我没有嵌套计算,我没有调用computecopy,并且我用来进行计算的所有内容都在同一个monad内。这与惰性评估有关吗?如果是这样,如何在使用 Identity monad 时进行并行计算(以保持整体计算的纯净)?

作为引用,将 runIdentity 替换为 runST 使其可以工作,尽管在任何一种情况下都根本没有使用特定 monad 的功能。

最佳答案

在computeP 和类似的并行操作中使用Monad 约束的原因是为了在需要时强制进行顺序计算。这在[Haskell 中的并行和并发编程]Monads 和computeP 小节中进行了描述。

就您而言,问题似乎是由 mmultP 的内部实现引起的:

mmultP  :: Monad m
        => Array U DIM2 Double 
        -> Array U DIM2 Double 
        -> m (Array U DIM2 Double)

mmultP arr brr 
 = [arr, brr] `deepSeqArrays` 
   do   trr      <- transpose2P brr
        let (Z :. h1  :. _)  = extent arr
        let (Z :. _   :. w2) = extent brr
        computeP 
         $ fromFunction (Z :. h1 :. w2)
         $ \ix   -> R.sumAllS 
                  $ R.zipWith (*)
                        (unsafeSlice arr (Any :. (row ix) :. All))
                        (unsafeSlice trr (Any :. (col ix) :. All))

它首先调用 transpose2P,然后调用 computeP,并且 transpose2P 在内部调用 computeUnboxedP。如果您使用 Identity monad,则不会强制排序,因此这两个并行计算都可以并行运行,从而实现嵌套并行性。

如果您想保持纯粹,又不想使用 ST,则可以将 Identity 替换为 Eval ,这是 Identity 的严格版本:

import Control.Parallel.Strategies
...
go = runEval $ do ...

关于haskell - 使用 repa 时将 Identity monad 与 mmultP 一起使用有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37782489/

相关文章:

haskell - 这个发电机组发电功能是如何工作的

haskell - 如何漂亮地打印记录类型?

arrays - MPI 可以收集、减少、发送或接收 Fortran 派生类型吗?

go - 如何在 Golang 中实现适当的并行性? goroutines 在 1.5+ 版本中是并行的吗?

c# - 线程安全类是否应该在其构造函数的末尾设置内存屏障?

haskell - 如何导入Repa

haskell - 使用 Haskell repa 数组库进行彩色图像文件 IO

haskell - 为什么 (>>) 没有定义为 (*>)?

Haskell - 异构数组?

haskell - Repa 性能与列表