mmultP
私は次のコードで関数をテストしていましたrepa-algorithms-3.2.1.1
(簡潔にするためにここに少し要約します):
import Data.Array.Repa hiding (map)
import Data.Array.Repa.Algorithms.Matrix (mmultP)
import Control.Monad (replicateM)
import Control.Arrow ((&&&))
import System.Random.MWC (initialize, uniformR)
import Control.Monad.ST (runST)
import Data.Vector.Unboxed (singleton)
import Data.Word (Word32)
-- Create a couple of dense matrices
genRnds :: Word32 -> [Double]
genRnds seed = runST $ do
gen <- initialize (singleton seed)
replicateM (1000 ^ 2) (uniformR (0, 1) gen)
(arr, brr) = head &&& last $ map (fromListUnboxed (Z :. 1000 :. 1000 :: DIM2) . genRnds) [1, 100000]
-- mmultP test
main :: IO ()
main = mmultP arr brr >>= print
ここで指定されているように、
ghc mmultTest.hs -Odph -rtsopts -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3 -fforce-recomp
スレッドランタイムでの順次実行は次のとおりです。
$ time ./mmultTest +RTS -K100M > /dev/null
real 0m10.962s
user 0m10.790s
sys 0m0.161s
これが4コアを使用したものです(4コアMacBook Airで実行):
$ time ./mmultTest +RTS -N4 -K100M > /dev/null
real 0m13.008s
user 0m18.591s
sys 0m2.067s
ここで何が起こっているのか、誰か直感がありますか?-N2
また、とのパフォーマンスが順次より遅くなり-N3
ます。各コアは、さらに時間を追加するようです。
手巻きのRepa行列乗算コードでは、並列処理によるわずかな向上が見られることに注意してください。
更新:
不可解; に置き換えmain
ました
mmultBench :: IO ()
mmultBench = do
results <- mmultP arr brr
let reduced = sumAllS results
print reduced
との依存関係を削除しましたmwc-random
:
(arr, brr) = head &&& last $ map (fromListUnboxed (Z :. 1000 :. 1000 :: DIM2)) (replicate 2 [1..1000000])
ランタイムオプションを使用したCriterionベンチマークでは、次の-N1 -K100M
結果が得られます。
mean: 1.361450 s, lb 1.360514 s, ub 1.362915 s, ci 0.950
std dev: 5.914850 ms, lb 3.870615 ms, ub 9.183472 ms, ci 0.950
そして-N4 -K100M
私に与える:
mean: 556.8201 ms, lb 547.5370 ms, ub 573.5012 ms, ci 0.950
std dev: 61.82764 ms, lb 40.15479 ms, ub 102.5329 ms, ci 0.950
これは素敵なスピードアップです。以前の動作は、結果の1000x1000配列をstdoutに書き込んだことによるものだとほぼ思いますが、前述したように、独自の行列乗算コードを交換すると、並列処理の向上が見られます。まだ頭をかいて。