我尝试在connected components
上运行logNormalGraph
。
val graph: Graph[Long, Int] = GraphGenerators.
logNormalGraph(context.spark, numEParts = 10, numVertices = 1000000,
mu = 0.01, sigma = 0.01)
val minGraph = graph.connectedComponents()
在下一个工作的火花UI中,我可以看到不断增加的跳过阶段数
1 - 4/4 (12 skipped)
2 - 4/4 (23 skipped)
...
50 - 4/4 (4079 skipped)
为什么我在Pregel上运行的东西有这么多跳过的阶段以及为什么这个数字增长如此之快(非线性)?
答案 0 :(得分:9)
一步一步。使用is implemented connectedComponents
函数Pregel API。忽略算法特定的细节迭代:
首先让我们创建虚拟sendMsg
:
import org.apache.spark.graphx._
def sendMsg(edge: EdgeTriplet[VertexId, Int]):
Iterator[(VertexId, VertexId)] = {
Iterator((edge.dstId, edge.srcAttr))
}
vprog
:
val vprog = (id: Long, attr: Long, msg: Long) => math.min(attr, msg)
和megeMsg
:
val mergeMsg = (a: Long, b: Long) => math.min(a, b)
接下来我们可以initialize示例图表:
import org.apache.spark.graphx.util.GraphGenerators
val graph = GraphGenerators.logNormalGraph(
sc, numEParts = 10, numVertices = 100, mu = 0.01, sigma = 0.01)
.mapVertices { case (vid, _) => vid }
val g0 = graph
.mapVertices((vid, vdata) => vprog(vid, vdata, Long.MaxValue))
.cache()
和messages:
val messages0 = g0.mapReduceTriplets(sendMsg, mergeMsg).cache()
由于GraphXUtils
是私有的,我们必须直接使用Graph
方法。
当您查看由
生成的DAG时messages0.count
您已经看到了一些跳过的阶段:
执行第一个iteration
后val g1 = g0.joinVertices(messages0)(vprog).cache()
val messages1 = g1.mapReduceTriplets(sendMsg, mergeMsg).cache()
messages1.count
图表看起来或多或少会像这样:
如果我们继续:
val g2 = g1.joinVertices(messages1)(vprog).cache()
val messages2 = g2.mapReduceTriplets(sendMsg, mergeMsg).cache()
messages2.count
我们得到以下DAG:
所以这里发生了什么:
g
在每次迭代中所依赖的阶段数增加g0
,messages0
)后,只会从头开始计算最新阶段。DAG
,您会发现存在相当复杂的依赖关系,这应该可以解释DAG相对缓慢增长与跳过阶段数之间的差异。第一个属性解释了越来越多的阶段,第二个属性是跳过阶段的事实。