より大きな問題の一部として、次のように配列内で配列を定義しようとしています。
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
ており、ルックアップ関数が提供されていますが、同じ効果のためにtraverse
andを使用することもできます。andをできるだけ早くarr ! ...
使用したにもかかわらず、コンソールには次のメッセージが表示され、その後に正しい結果が表示されます。force
deepSeqArray
Data.Array.Repa: ネストされた並列計算を順次実行します。別のインスタンスが既に実行されているときに、おそらく「強制」関数を呼び出しました。これは、遅延評価のために 2 番目のバージョンが中断された場合に発生する可能性があります。「deepSeqArray」を使用して、次の配列を「強制」する前に各配列が完全に評価されるようにします。
速度を比較するためのリストを含むバージョンを構築していませんが、より大きなバージョンではパフォーマンスが低下しています。
これは単にネストされた配列定義の結果なので、内部定義または外部定義のいずれかがリストになるようにプログラムを再構築する必要がありますか? 私のextract
機能はひどいものであり、問題の原因ですか?
この質問 からのヒントは、ここまで到達するのに役立ちましたが、コンパイルされたコードをまだクロールしていません。