【问题标题】:How much overhead does sparking incur?火花产生多少开销?
【发布时间】:2014-07-15 16:14:27
【问题描述】:

“并行和并发编程”中的这张图:http://chimera.labs.oreilly.com/books/1230000000929/ch03.html#fig_kmeans-granularity 起初似乎表明触发过多会产生严重的开销。但是,如果您仔细查看 y 轴,您会注意到它已被放大到有趣的部分。事实上,显示的最佳和最差情况性能之间的比率约为 80%,这还不算太差。

一般来说,弄清楚如何分块以及分块多少是困难的、容易出错的、极其特定于应用程序的,并且当您购买具有更强处理能力的新计算机时,明年可能会发生变化。我更愿意始终将 rpar 用于尽可能细粒度的项目,并承受 25% 的开销。

引发火花的开销通常会比此图中显示的成本高得多吗? (特别是如果我总是折叠二叉树而不是列表,那么关于“顺序工作量”的第二个要点不适用)


针对唐·斯图尔特的回答更新了问题:

火花池是否仅包含一个所有处理器都难以访问的队列?还是有很多?

例如,如果我有一台具有无限处理器和二叉树的计算机,并且我想对所有叶子求和,如下所示:

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 并行性如何工作的心智模型仍然很模糊。

【问题讨论】:

  • 使用并行运行时,每个使用的 HEC(处理器)都有一个队列,我记得 c 正确。这在 Don 链接的论文中都有描述。

标签: multithreading haskell parallel-processing overhead moores-law


【解决方案1】:

一个火花很便宜。

  • 火花池。每次调用 par a b 都会将 thunk a 添加到 (当前 HEC 的)Spark Pool;这种重击称为“火花”。 [1]

如果任何 HEC 空闲,它可以检查池并开始评估顶部的 thunk。

所以 sparking 大致就是添加一个指向队列的指针。

为了使 Spark 分发更便宜、更异步,我们 将每个 HEC 的 Spark Pool 重新实现为有界工作窃取队列 (Arora 等人,1998 年;Chase 和 Lev 2005 年)。工作窃取队列是 具有一些吸引人的特性的无锁数据结构: 队列可以在不同步的情况下从一端推送和弹出, 同时其他线程可以从队列的另一端“窃取” 只产生一条原子指令。

同样在[1]

问题在于您可以轻松地创造出数十亿个火花。那时,您只是将您的程序变成了一个队列构建器——所有时间都花在使用指向代码的指针来更新火花池。

好的建议是分析,确定有多少火花实际转化为工作,并以此来指导何时停止火花的阈值。

【讨论】:

  • 通过不锁定火花池可以使火花更便宜,例如,每个处理器有一个池并依赖文字写入是原子的。
  • 伦纳特好点。更新以描述现在使用的无锁队列。
  • @DonStewart 哇,谢谢!这个答案给了我一些见解,但我仍然不完全清楚。你能看看我更新的问题吗?
猜你喜欢
  • 2010-10-07
  • 2011-08-23
  • 2014-02-17
  • 1970-01-01
  • 2017-05-13
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多