Haskell - 平行映射,减少火花

时间:2011-05-11 18:32:24

标签: performance haskell parallel-processing multicore

我想在Haskell中编写一个尽可能高效的并行映射函数。我最初的尝试,似乎是目前最好的,只是写,

pmap :: (a -> b) -> [a] -> [b]
pmap f = runEval . parList rseq . map f
但是,我没有看到完美的CPU划分。如果这可能与火花的数量有关,我是否可以编写一个将列表分成#of cpus 段的pmap,因此创建了最少的火花?我尝试了下面这个,但是性能(和火花的数量)要差得多,

pmap :: (a -> b) -> [a] -> [b]
pmap f xs = concat $ runEval $ parList rseq $ map (map f) (chunk xs) where
    -- the (len / 4) argument represents the size of the sublists
    chunk xs = chunk' ((length xs) `div` 4) xs
    chunk' n xs | length xs <= n = [xs]
                | otherwise = take n xs : chunk (drop n xs)

性能较差可能与较高的内存使用率相关。最初的pmap确实在24核系统上有所扩展,所以并不是因为我没有足够的数据。 (我桌面上的CPU数量是4,所以我只是硬编码了。)

编辑1

使用+RTS -H512m -N -sstderr -RTS的一些效果数据来自:

1 个答案:

答案 0 :(得分:9)

parallel包为您定义了许多并行地图策略

parMap :: Strategy b -> (a -> b) -> [a] -> [b]

parList和map的组合,以及对列表进行分块的特定支持:

parListChunk :: Int -> Strategy a -> Strategy [a]

将列表划分为块,并将策略evalList strat并行应用于每个块。

您应该能够使用这些组合来获得您想要的任何引发行为。或者,为了更多控制,the Par monad包,用于控制创建的线程数量(纯粹)。


参考文献: haddock docs for the parallel package