rit*_*mon 6 parallel-processing haskell 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
Run Code Online (Sandbox Code Playgroud)
给我以下警告:
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.
Run Code Online (Sandbox Code Playgroud)
我没有嵌套计算,我没有调用compute或者copy,我用来进行计算的所有东西都在同一个monad中.是否与懒惰评估有关?如果是这样,如何在使用Identity monad时进行并行计算(以保持整体计算纯净)?
作为参考,取代runIdentity以runST使得它的工作,但在两种情况下,具体的单子的功能不被使用的.
Monad在并行操作和类似并行操作中具有约束的原因computeP是在需要时强制进行顺序计算。这在 [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))
Run Code Online (Sandbox Code Playgroud)
它先调用transpose2P后调用computeP,transpose2P内部调用computeUnboxedP。如果您使用Identitymonad,则不会强制排序,因此这两个并行计算都可以并行运行,从而实现嵌套并行性。
如果你想保持纯粹并且不想使用ST,你可以替换Identity为Eval,这是 的严格版本Identity:
import Control.Parallel.Strategies
...
go = runEval $ do ...
Run Code Online (Sandbox Code Playgroud)