2017-12-20 9 views
2

リストのためにベクトルのために行う関数が必要です。parMap rparここに私が持っているものがあります:Haskellでのベクトル上の並列マッピング

import Data.Vector 
import Control.Parallel.Strategies 

parMapVec :: (a -> b) -> Vector a -> Vector b 
parMapVec f = map (runEval . rpar . f) 

私は、これがどういうわけか、またはなぜそれがうまくいかないのか、完全に理由を突き止めることはできません。

別の解決策は、TraversableVectorインスタンスを作成し、その後parTraversableを使用するかもしれないが、それはちょうどparMap rparのような何かを得るために多くの作業のように思えます。

+4

ここでは正確には何が機能しないのですか?エラーはありますか?もしそうなら、ここに書いてください。 – AJFarmar

+3

[vector strategies](https://hackage.haskell.org/package/vector-strategies-0.4/docs/Data-Vector-Strategies.html)パッケージの使用を検討してください。 –

+1

@ ThomasM.DuBuissonここにパッケージが必要なのはなぜですか?パッケージにはちょうど1つの機能があり、その本体は1行の長さです。 – Alec

答えて

0

Vectorは実際には、lierdakilによって指摘されているTaversableのインスタンスです。私はそれがこのことを知っData.Traversable page.

にインスタンスとしてリストされていないので、それがないと思った、私はいくつかのテストを実行しました:

import Control.Parallel.Strategies 
import Data.Vector as V 
import Data.Maybe 

parMapVec :: (a -> b) -> Vector a -> Vector b 
parMapVec f v = runEval $ evalTraversable rpar $ V.map f v 

range :: Integer -> Integer -> Vector Integer 
range x y 
    | x == y = x `cons` empty 
    | x < y = x `cons` (range (x + 1) y) 
    | x > y = (range x (y + 1)) `snoc` y 

fac :: Integer -> Integer 
fac n 
    | n < 2  = 1 
    | otherwise = n * (fac $ n - 1) 

main :: IO() 
main = do 
    let result = runEval $ do 
     let calc = parMapVec fac $ 80000 `range` 80007 
     rseq calc 
     return calc 
    putStrLn $ show result 

私はghc --make ParVectorTest.hs -threaded -rtsoptsでこれをコンパイルし./ParVectorTest -sでそれを実行してい私はプロセスが私のシステムモニタ上で実行見て、コアがあったと見て、代わりに、すべての計算の間のトレードオフ、同時に階乗を計算することを除いて、良好であることを

SPARKS: 8 (7 converted, 0 overflowed, 0 dud, 0 GC'd, 1 fizzled) 

INIT time 0.001s ( 0.001s elapsed) 
MUT  time 5.460s ( 5.447s elapsed) 
GC  time 15.916s (15.893s elapsed) 
EXIT time 0.000s ( 0.000s elapsed) 
Total time 21.380s (21.342s elapsed) 

これが懸念されるので、私はmainは、次のように修正されたテストでした:私はコンパイルして、それを見つけるのと同じ方法で実行されていました

main = do 
    let result = runEval $ do 
     let calc = parMap rpar fac [80000..80007] 
     rseq calc 
     return calc 
    putStrLn $ show result 

を:

SPARKS: 16 (14 converted, 0 overflowed, 0 dud, 1 GC'd, 1 fizzled) 

INIT time 0.001s ( 0.001s elapsed) 
MUT  time 5.412s ( 5.418s elapsed) 
GC  time 18.583s (18.537s elapsed) 
EXIT time 0.001s ( 0.000s elapsed) 
Total time 23.999s (23.957s elapsed) 

私は」なぜ8の代わりに16のスパークがあったのか分かりませんが、その点以外にもあると思います。このバージョンでは、実際に並列に実行されるのではなく、プロセッサ間で渡される計算と同じ動作を示しました。

したがって、リストを使用しているプログラムも、ベクトルを使用しているプログラムも完全に並行して実行されているわけではありませんが、若干高速なベクトルのバージョンはparMap rparです。

編集:オリジナルのバージョンparMapVecを使用して同じテストを実行し、すべてのスパークが飛び散ったことを追加する必要がありますが、理由は説明できません。

関連する問題