【发布时间】:2011-08-02 03:30:49
【问题描述】:
是否有一些 map 的替代品可以并行评估列表?我不需要它偷懒。
类似:pmap :: (a -> b) -> [a] -> [b] 让我 pmap expensive_function big_list 并让我所有的核心都达到 100%。
【问题讨论】:
标签: haskell parallel-processing multicore combinators
是否有一些 map 的替代品可以并行评估列表?我不需要它偷懒。
类似:pmap :: (a -> b) -> [a] -> [b] 让我 pmap expensive_function big_list 并让我所有的核心都达到 100%。
【问题讨论】:
标签: haskell parallel-processing multicore combinators
除了像 Tom 所描述的那样自己使用显式策略之外,parallel 包 also exports parMap:
parMap :: Strategy b -> (a -> b) -> [a] -> [b]
策略参数类似于rdeepseq。
par-monad 包中还有 parMap(你走出纯 Haskell,进入并行 monad):
parMap :: NFData b => (a -> b) -> [a] -> Par [b]
par-monad 包是documented here。
【讨论】:
是的,见parallel package:
ls `using` parList rdeepseq
将通过rdeepseq 策略并行评估列表中的每个元素。请注意,如果您的元素太便宜而无法获得并行评估每个元素的好处(因为它可以节省每个元素的火花),则使用具有良好块值的 parListChunk 可能会提供更好的性能。
编辑:根据您的问题,我觉得我应该解释为什么这是一个答案。这是因为 Haskell 很懒!考虑声明
let bs = map expensiveFunction as
没有进行任何评估。您刚刚创建了一个映射 expensiveFunction 的 thunk。那么我们如何并行评估呢?
let bs = map expensiveFunction as
cs = bs `using` parList rdeepseq
现在不要在以后的计算中使用bs 列表,而是使用cs 列表。 IOW,您不需要并行映射,您可以使用常规(惰性)映射和并行评估策略。
编辑:如果您环顾四周,您会看到 parMap 函数,它执行我在此处显示的操作,但封装在一个辅助函数中。
针对您的评论,以下代码对您不起作用吗?它对我有用。
import Control.Parallel.Strategies
func as =
let bs = map (+1) as
cs = bs `using` parList rdeepseq
in cs
【讨论】:
pmap f x = (map f x) `using` parList rdeepseq,但 GHC 抱怨 rdeepseq 需要一个参数。
parMap rdeepseq f as 应该做同样的事情。
NFData 实例——这是使用rdeepseq 所必需的。如果这太繁琐,那么请改用rseq,它会评估为 whnf。
ghc -O2 -threaded blah.hs --make) 进行编译并使用正确的 RTS 选项 (./blah +RTS -Nx) 其中 x 是您要使用的内核数,例如 2 ?请注意,在 GHC 7 上,您应该只能输入 ghc -O2 -threaded -with-rtsopts=-N blah.hs 并运行 ./blah。