4

より大きな問題の一部として、次のように配列内で配列を定義しようとしています。

import Data.Array.Repa
type Arr = Array DIM2 Int

arr = force $ fromList (Z :. 5 :. 5) [1..25] :: Arr

combined :: Arr
combined = arr `deepSeqArray` 
    traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) (\f (Z :. x :. y) -> 
        let reg = force $ extract f (x,y) (2,2)
        in  reg `deepSeqArray` sumAll reg)

extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Arr
extract lookup (x0,y0) (width,height) = fromFunction bounds 
  $ \sh -> offset lookup sh
    where 
    bounds = Z :. width :. height
    offset :: (DIM2 -> Int) -> DIM2 -> Int
    offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0)

main = print combined

extract関数は使用されfromFunctionており、ルックアップ関数が提供されていますが、同じ効果のためにtraverseandを使用することもできます。andをできるだけ早くarr ! ...使用したにもかかわらず、コンソールには次のメッセージが表示され、その後に正しい結果が表示されます。forcedeepSeqArray

Data.Array.Repa: ネストされた並列計算を順次実行します。別のインスタンスが既に実行されているときに、おそらく「強制」関数を呼び出しました。これは、遅延評価のために 2 番目のバージョンが中断された場合に発生する可能性があります。「deepSeqArray」を使用して、次の配列を「強制」する前に各配列が完全に評価されるようにします。

速度を比較するためのリストを含むバージョンを構築していませんが、より大きなバージョンではパフォーマンスが低下しています。

これは単にネストされた配列定義の結果なので、内部定義または外部定義のいずれかがリストになるようにプログラムを再構築する必要がありますか? 私のextract機能はひどいものであり、問​​題の原因ですか?

この質問 からのヒントは、ここまで到達するのに役立ちましたが、コンパイルされたコードをまだクロールしていません。

4

1 に答える 1

2

これは、「print」が暗黙的に配列も強制するためです。内部の 'force' および 'sumAll' 関数は並列計算を呼び出しますが、'print' を実行するため、ネストされた並列処理が行われます。これが非常に明白ではないという事実は、Repa 2 API の大きな悲しみです。

Repa 3 は、「force」や「sumAll」などのシーケンシャル バージョンとパラレル バージョンの両方をエクスポートすることで、この種の問題に対処します。また、アレイ タイプにタグを追加して、アレイが遅延かマニフェストかを示します。Repa 3 はまだ完成していませんが、http://code.ouroborus.net/repaで head バージョンを使用できます。今年後半の GHC 7.4 のすぐ後にリリースされる予定です。

これは、ネストされた並列処理に関する警告を表示せずに実行される例の Repa 3 バージョンです。'force' が 'compute' になったことに注意してください。

import Data.Array.Repa

arr :: Array U DIM2 Int
arr = fromListUnboxed (Z :. 5 :. 5) [1..25]

combined :: Array U DIM2 Int
combined 
  = computeP $ traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) 
  $ \f (Z :. x :. y) -> sumAllS $ extract f (x,y) (2,2)

extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Array D DIM2 Int
extract lookup (x0,y0) (width,height) 
  = fromFunction bounds 
  $ \sh -> offset lookup sh
    where 
    bounds = Z :. width :. height
    offset :: (DIM2 -> Int) -> DIM2 -> Int
    offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0)

main = print combined
于 2011-11-23T03:30:13.310 に答える