我对 Spark 很陌生,但已经有 BSP 模型的编程经验。在 BSP 模型中(例如 Apache Hama),我们必须自己处理所有节点的通信和同步。这一方面是好的,因为我们可以更好地控制我们想要实现的目标,但另一方面它增加了更多的复杂性。
另一方面,Spark 拥有所有控制权并自行处理所有事情(这很棒),但我不明白它是如何在内部工作的,尤其是在我们在节点之间传递大量数据和消息的情况下。让我举个例子
zb = sc.broadcast(z)
r_i = x_i.map(x => Math.pow(norm(x - zb.value), 2))
r_i.checkpoint()
u_i = u_i.zip(x_i).map(ux => ux._1 + ux._2 - zb.value)
u_i.checkpoint()
x_i = f.prox(u_i.map(ui => {zb.value - ui}), rho)
x_i.checkpoint()
x = x_i.reduce(_+_) / f.numSplits.toDouble
u = u_i.reduce(_+_) / f.numSplits.toDouble
z = g.prox(x+u, f.numSplits*rho)
r = Math.sqrt(r_i.reduce(_+_))
这是一种取自此处的方法,它循环运行(比如说 200 次)。x_i 包含我们的数据(假设有 100,000 个条目)。
在 BSP 风格的程序中,如果我们必须处理这个映射操作,我们将把这些数据分区并分布在多个节点上。每个节点将处理子部分数据(映射操作)并将结果返回给主节点(在屏障同步之后)。由于主节点想要处理返回的每个单独的结果(集中式主节点-见下图),我们将每个条目的结果发送给主节点(Spark 中的reduce运算符)。因此,(仅)master 在每次迭代后收到 100,000 条消息。它处理这些数据并再次将新值发送到从站,从站再次开始处理下一次迭代。
现在,由于 Spark 从用户那里获得控制权并在内部完成所有操作,我无法理解 Spark 在 map 操作之后如何收集所有数据(异步消息传递?我听说它有 p2p 消息传递?map 任务之间的同步呢?如果有的话同步,那么说Spark其实是BSP模型对吗?)。然后为了应用reduce函数,它是在中央机器上收集所有数据(如果是,它是否在单台机器上接收100,000条消息?)还是以分布式方式减少(如果是,那么这怎么可能?执行?)
下图显示了我在 master 上的 reduce 功能。x_i^k-1 表示针对我输入的 x_i 数据条目计算的第i个值(在之前的迭代中)。x_i^k 表示在当前迭代中计算的 x_i 的值。显然,这个方程需要收集结果。
我实际上想比较两种分布式编程风格,以了解何时使用 Spark 以及何时迁移到 BSP。此外,我在互联网上看了很多,我发现的只是 map/reduce 的工作原理,但在实际通信/同步方面没有任何有用的东西。任何有用的材料也将是有用的。