我是從repa-algorithms-3.2.1.1
檢驗出mmultP
功能用下面的代碼(在此冷凝爲簡潔起見一點點):在repA的的算法功能觀察到意外的性能
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
和如使用指定here,編譯
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芯(在四核的MacBook Air上運行):
$ time ./mmultTest +RTS -N4 -K100M > /dev/null
real 0m13.008s
user 0m18.591s
sys 0m2.067s
任何人有任何的直覺來這裏發生了什麼?我還獲得了-N2
和-N3
的慢於序列的性能;每個核心似乎都會增加一些額外的時間。
請注意,我在做觀察到一些手動軋製的Repa矩陣乘法代碼的一些小的收益。
UPDATE:
困惑;我換成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])
的判定基準與運行時選項-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所致,但正如我所提到的,如果我交換自己的矩陣乘法代碼,我確實會在那裏觀察到並行增益。仍在撓撓我的腦袋。
哪個GHC版本? – 2012-07-31 14:07:51
使用GHC 7.4.1。 – jtobin 2012-07-31 14:09:00
使用3核時,你會得到什麼? – 2012-07-31 15:04:00