この質問の続きです。unsafeFreeze
ベクトル ライブラリには融合可能な O(1) 更新関数がないようなので、 andを含まない融合可能な O(1) 更新関数を記述できないか考えていunsafeThaw
ます。それはvector stream
表現を使用すると思います-私は表現を使用して書く方法に慣れていませんstream
-unstream
したがって、この質問です。その理由は、これにより、ベクターの狭い領域のみが変更されるキャッシュに適した更新関数をベクターに書き込むことができるようになるためです。そのため、その狭い領域を処理するためだけにベクター全体をウォークスルーしたくありません (この操作は、各関数呼び出しで何十億回も発生する可能性があるため、オーバーヘッドを非常に低く保つ動機になります)。変換関数は次のようになりますmap
ベクトル全体を処理するため、処理が遅くなります。
私がやりたいことのおもちゃの例がありますが、upd
以下の関数はunsafeThaw
andを使用していますunsafeFreeze
- それはコアで最適化されていないようで、さらにバッファを使用しないという約束を破っています:
module Main where
import Data.Vector.Unboxed as U
import Data.Vector.Unboxed.Mutable as MU
import Control.Monad.ST
upd :: Vector Int -> Int -> Int -> Vector Int
upd v i x = runST $ do
v' <- U.unsafeThaw v
MU.write v' i x
U.unsafeFreeze v'
sum :: Vector Int -> Int
sum = U.sum . (\x -> upd x 0 73) . (\x -> upd x 1 61)
main = print $ Main.sum $ U.fromList [1..3]
を使用して命令型アルゴリズムを実装する方法を知っていますSTVector
。なぜこの代替アプローチが必要なのか疑問に思われている方のために、純粋なベクトルを使用GHC
して特定のアルゴリズムの変換が、融合可能な純粋なベクトル ストリームを使用して記述された場合 (もちろんボンネットの下でモナド演算を使用して) を使用してどのように異なるかを確認するこのアプローチを試してみたいと思います。
を使用してアルゴリズムを作成するSTVector
と、私が望むほどうまく反復処理されないように見えます (多くの可変性が散らばっている場合、GHC オプティマイザがループを見つけるのは難しいと思います)。そのため、私はこの代替アプローチを調査して、より良いループを取得できることを確認しています。