Haskell中向量的并行映射

时间:2017-12-20 23:41:28

标签: haskell vector parallel-processing

我想要一个为parMap rpar列表所做的向量做的函数。这就是我所拥有的:

import Data.Vector
import Control.Parallel.Strategies

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

我无法完全推断出这将如何或为何会起作用。

另一个解决方案可能是让Vector成为Traversable的一个实例,然后使用parTraversable,但这似乎只是为了得到像parMap rpar这样的东西。

1 个答案:

答案 0 :(得分:1)

正如lierdakil所指出的,

Vector确实是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)

我不确定为什么会有16个火花而不是8火花,但我认为除此之外还有。此版本还演示了在处理器之间传递的计算的相同行为,而不是实际并行执行。

所以,我有一个parMap rpar版本的矢量稍微快一些,尽管程序使用列表和使用矢量完全并行运行的程序都是关注的事实。

编辑:我应该补充一点,我使用原始版本的parMapVec运行相同的测试并且所有火花都失败了,尽管我无法解释原因。