并行和并发编程中的这个图表":http://chimera.labs.oreilly.com/books/1230000000929/ch03.html#fig_kmeans-granularity起初似乎表明引发太多的严重开销。但是如果仔细观察y轴,你会注意到它被放大到了有趣的部分。事实上,最佳和最差案例表现之间的比例约为80%,这并不算太差。
一般来说,弄清楚块的方式和数量是困难的,容易出错,极其特定于应用程序,并且当你购买具有更强处理能力的新计算机时,明年可能会改变。我更倾向于总是使用rpar来获得最细粒度的物品,并以25%的开销生活。
引发的开销通常会产生比此图所示更低的成本吗? (特别是如果我总是折叠二叉树而不是列表,那么关于"顺序工作量"不适用的第二个要点)
针对Don Stewart的回答更新了问题:
火花池是否只包含一个所有处理器都难以访问的队列?或者有很多?
例如,如果我的计算机具有无限处理器和二叉树,我想在所有叶子上取总和,如下所示:
data Node = Leaf Int | Branch Node Node
sumL (Leaf x) = x
sumL (Branch n1 n2) = let (x,y) = (sumL n1, sumL n2) in (x `par` y) `seq` (x + y)
这个程序会在O(#leaves)时间运行吗?或O(深度)时间? 有没有更好的方法来写这个?
如果我抽出太多东西以获得满意的答案,请告诉我。我对haskell并行性如何运作的心理模型仍然非常模糊。
答案 0 :(得分:9)
单一火花很便宜。
par a b
都会将thunk添加到。{
(现在的HEC)Spark Pool;这个thunk被称为“火花”。 [1] 如果任何HEC变为空闲,它可以检查池并开始评估顶部的thunk。
因此,引发大致是添加一个指向队列的指针。
使我们的火花分配更便宜,更异步 将每个HEC的Spark Pool重新实现为有界的工作流队列 (Arora等,1998; Chase和Lev,2005)。一个工作队列是一个 具有一些吸引力的属性的无锁数据结构:所有者 队列可以在没有同步的情况下从一端推送和弹出, 同时其他线程可以从队列的另一端“窃取” 只产生一条原子指令。
同样在[1]
问题在于您可以轻松创建数十亿个火花。那时,您只需将程序转换为队列构建器 - 所有时间都花在使用指向代码的指针上更新火花池。
好的建议是分析,确定实际上有多少火花被转化为工作,并用它来指导何时停止火花的阈值。