2016-06-13 35 views
6

我不明白为什么这个程序使用repa在使用repa时使用Identity monad和mmultP有什么问题?

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时如何使并行计算发生(保持整体计算纯粹)?

仅供参考,用runST代替runIdentity可以使其工作,但在任何情况下都不会使用特定monad的功能。

+0

的源代码里面看,我看'mmultP'调用'computeP',它调用'unsafePerformIO'。我对此并不是很有经验,但是'unsafePerformIO'和'Identity'单子之间可能存在不兼容(也许'身份'的行为与懒惰)? – madjar

+0

@madjar我不知道。我不知道如何。 – rityzmon

回答

2

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,你可以用Eval取代Identity,这是Identity严格的版本:

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

谢谢。我对这种根深蒂固的“身份”单子没有进行排序的困惑受到了强迫。为什么?它不是一个使用'>> ='进行排序的monad吗? – rityzmon

+0

Monads描述计算,但一般不是如何评估它们。对于一些monad来说,这个命令是强制执行的('IO','ST','Eval',...),但对于一些monad而言('Reader','Identity',...)。 Haskell的懒惰评估仍然适用,所以如果顺序不是强制的,计算仍然是懒惰评估。特别是,“身份”是一个完全没有做任何事情的monad,它只给单纯的计算接口。 –

相关问题