repaに(//)の類似物があるのだろうか?
並列化できない配列変換に必要です。たとえば、関数が配列全体で配列の1つのエントリを変更する必要があり、それが新しい配列に適用される場合など(そして、順次実行する必要があります)。
(//)
Data.Array.Repa.fromFunctionの観点から実装できます。
import Data.Array.Repa
(//) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(//) arr us = fromFunction (extent arr) (\sh -> case lookup sh us of
Just a -> a
Nothing -> index arr sh)
fromFunction
Shape sh => s -> a
それ自体が配列全体を利用できるタイプの関数を渡すことができます。
上記の実装は、1回のパスですべての更新を実行します。
(//)の潜在的な問題の1つは、リストを検索して各要素の値を見つける必要があることです。配列またはリストが大きい場合、これは高額になる可能性があります。
もう1つのオプションは、Data.Vectorの便利な関数を利用することです。
modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
これにより、安全であれば更新を実行できる可能性があります。だから何かのような
import Data.Vector.Unboxed as V
import Data.Vector.Mutable.Unboxed as M
import Data.Array.Repa as R
(///) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(///) arr us = R.fromVector sh . modify f $ R.toVector arr
where
sh = extent arr
f mv = forM_ us $ \(k,x) -> do
M.write mv (R.toIndex sh k) x
私のラップトップでは、これを100万要素のDIM1アレイでテストし、100エントリを更新して、次の時間を取得しました:(//):3.598973(///):2.0859999999999997e-3