我试图弄清楚 Haskell 的 Control.Parallel 模块,我写了以下内容(tMap 是时间比较的基本案例):
import Control.Parallel
paraMap, tMap :: (a -> b) -> [a] -> [b]
paraMap _ [] = []
paraMap f [x] = [f x]
paraMap f (x : xs@(y : ys)) = (f y `par` f x) : paraMap f xs
tMap _ [] = []
tMap f (x : xs) = f x : tMap f xs
这个想法是 paraMap 将在完成当前元素之前开始计算下一个元素。我的测试表明它的性能比 tMap 差。我猜这是因为 par 引入了更多开销,并且因为我没有正确使用它,它没有产生足够的 yield 来克服成本。
我上面的例子有什么问题?据我了解,
x 'par' y
基本上意味着“我需要 x
稍后,所以并行计算它,但现在返回 y
”(类似于 seq 的工作方式,但体现在 spark 中,这允许它有可能在单独的线)。我唯一能想到的就是它被混淆了,因为我需要函数的单独实例中的下一个元素(递归)。我想我可以制作
paraMap
实际递归的包装,并显式传递下一个 par
'd 元素到下一个递归;但这似乎很笨拙。我尝试用
:! ghc -o -threaded <fileName> "<fileName><fileExt>" +RTS -s
编译它来调试它(格式化为 GHCi 中的工具),我的主要内容如下:main = print $ paraMap (\x -> foldl (+) 0 [1..x * 100]) [1..500]
并收到以下反馈:
75,657,304 bytes allocated in the heap
32,738,472 bytes copied during GC
8,926,880 bytes maximum residency (7 sample(s))
139,208 bytes maximum slop
19 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 82 colls, 0 par 0.02s 0.04s 0.0005s 0.0199s
Gen 1 7 colls, 0 par 0.08s 0.12s 0.0168s 0.0587s
TASKS: 5 (1 bound, 4 peak workers (4 total), using -N1)
SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.00s ( 0.15s elapsed)
MUT time 0.05s ( 0.30s elapsed)
GC time 0.09s ( 0.16s elapsed)
EXIT time 0.02s ( 0.01s elapsed)
Total time 0.16s ( 0.62s elapsed)
Alloc rate 1,614,022,485 bytes per MUT second
Productivity 40.0% of total user, 10.1% of total elapsed
gc_alloc_block_sync: 0
whitehole_spin: 0
gen[0].sync: 0
gen[1].sync: 0
除非我读错了,否则没有产生 Spark ,这绝对是一个问题。
我在想这完全错了吗?任何见解将不胜感激。
最佳答案
在这里,par
原因 f y
被激发,但它的结果从未被使用(它没有绑定(bind)到任何东西,所以你无法访问它):
paraMap f (x : xs@(y : ys)) = (f y `par` f x) : paraMap f xs
下次申请
f
在 y
(这将在对 f x
的递归调用中以 paraMap
的形式发生)对此引发的 f y
一无所知计算,因为您从未将其传递给它。一个更简单的例子,遇到同样的问题,就像
foo x y = bar x `par` bar y `pseq` bar x + bar y
同样,第二次调用
bar
无法访问已经触发的计算结果。相反,你应该写foo x y = let x' = bar x
y' = bar y
in x' `par` y' `pseq` x' + y'
关于haskell - 我误解了 Haskell 的 Control.Parallel 并想澄清,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26837820/