2016-06-13 1 views
6
このプログラム repaを使用して、なぜ私は理解していない

repaを使用しているときに、mmultPでIDモナドを使用すると何が問題になりますか?

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を呼び出して、すべてのものはなかったです私が計算をしていたのは、同じモナドの中にあります。それは怠惰な評価とは何か?そうであれば、アイデンティティモナドを使用して並列計算を行う(全体の計算を純粋に保つために)方法を教えてください。

runIdentityrunSTに置き換えると、いずれの場合も特定のモナドの機能がまったく使用されていませんが、どちらの場合でも動作します。

+0

、私が見ます'mmultP'は' unsafePerformIO'を呼び出す 'computeP'を呼び出します。私はそれほど経験はありませんが、 'unsafePerformIO'と' Identity'モナド(おそらく 'Identity'の怠惰との動作)の間に互換性がないかもしれませんか? – madjar

+0

@madjarわかりません。私はどのように表示されません。 – rityzmon

答えて

2

computePと同様の並列操作でMonad制約を持つ理由は、必要に応じて強制的に逐次計算を行うためです。これは、サブセクションMonadsおよびcomputePの[Haskellにおける並列および並行プログラミング]で説明されています。あなたのケースでは

、問題は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モナドを使用すると、順序付けが強制されないため、これらの並列計算は両方とも並列に実行でき、したがってネストされた並列性が実行されます。

あなたは純粋なものを維持するためにもSTを使用したくない場合は、あなたがIdentityの厳格なバージョンである、EvalIdentityを置き換えることができます:ソースコード内で探し

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

ありがとうございます。これと私の混乱は、順序付けが強制されていない「アイデンティティ」モナドに根ざしていました。どうして?シーケンスするのに '> ='を使うモナドではありませんか? – rityzmon

+0

Monadsは計算を記述しますが、一般的に計算方法は記述されていません。いくつかのモナドでは、順序は強制されます( 'IO'、' ST'、 'Eval'、...)、いくつかのモナドでは(' Reader'、 'Identity'、...)。ハスケルの怠惰な評価がまだ適用されているので、注文が強制されなければ、計算は遅れて評価されます。特に、 'Identity'は全く何もしないモナドです。純粋な計算のためのモナドインターフェースしか与えません。 –

関連する問題