Edited at

hmatrixのSTVectorとVectorとの部分更新速度比較

More than 3 years have passed since last update.

ノイズの中に信号を埋め込んで、その信号が検出できるかどうかのテストを行うことを考える。その場合、データに信号を埋め込むことを行うので、データ列の一部分に変更することになる。そこで、データ列の一部分の変更を行う関数を書くために、データ型の更新速度を調べてみた。今回は

hmatrixのデータ型STVectorVectorとの比較をした。

方法としては、Vectorの方は、subVectorを用いて更新する部分としない部分に分けて、更新後にjoinするという方法

injectedV = join [subVector 0 n v

, add (subVector n nw v) w
, subVector (n+nw-1) (nv -nw -n) v]

をとり、STVectorの方は、Vector型のデータ列をunsafeThawVectorでSTVector型に変換して、in-placeの更新を行う方法

addInjsig n v w = runSTVector $ do

v' <- unsafeThawVector v
mapM_ (\i -> addInjsigCore v' w (n+i) i) [0 .. nw-1]
return v'
where
nw = dim w

をとった。

テストコードは以下である。

--- testbench_STVector.hs

import Control.DeepSeq (deepseq)
import Control.Monad.ST (ST)
import Data.Packed.ST
import Numeric.LinearAlgebra
import System.Random
import Data.Time

main = do
let v = fromList $ take 100000 $ randomRs (-10, 10) $mkStdGen 1 :: Vector Double
w = fromList $ take 1000 $ randomRs (-10, 10) $mkStdGen 2 :: Vector Double
n = 5000
nw = dim w
nv = dim v

v `deepseq` return ()
w `deepseq` return ()
nw `deepseq` return ()
nv `deepseq` return ()

t1 <- getCurrentTime
let injectedV = join [subVector 0 n v
, add (subVector n nw v) w
, subVector (n+nw-1) (nv -nw -n) v]
print $ injectedV @> 5500
t2 <- getCurrentTime
print $ diffUTCTime t2 t1

t3 <- getCurrentTime
let injectedST = addInjsig n v w
print $ injectedST @> 5500
t4 <- getCurrentTime
print $ diffUTCTime t4 t3

addInjsig n v w = runSTVector $ do
v' <- unsafeThawVector v
mapM_ (\i -> addInjsigCore v' w (n+i) i) [0 .. nw-1]
return v'
where
nw = dim w

addInjsigCore :: STVector s Double -> Vector Double -> Int -> Int -> ST s ()
addInjsigCore v w i j = modifyVector v i (+w@>j)

結果は以下のようになった。

スクリーンショット 2014-09-28 8.27.36.png

Vectorの方のコードは改善の余地がありそうだが、STVectorを用いたものはかなり速いという結果だった。

他の良いやり方のアイディアなどがあれば教えていただければありがたいです!