Spark - GraphX - 扩展连接组件

时间:2016-10-26 15:47:11

标签: apache-spark spark-graphx connected-components

我正在尝试使用连接组件,但是存在缩放问题。我的就是我的 -

// get vertices
val vertices = stage_2.flatMap(x => GraphUtil.getVertices(x)).cache

// get edges
val edges = stage_2.map(x => GraphUtil.getEdges(x)).filter(_ != null).flatMap(x => x).cache

// create graph  
val identityGraph = Graph(vertices, edges)

// get connected components
val cc = identityGraph.connectedComponents.vertices

其中,GraphUtil具有辅助函数来返回顶点和边。在这一点上,我的图表有大约100万个节点和大约200万个边缘(顺便说一下,预计这将增长到约1亿个节点)。我的图表非常稀疏 - 所以我希望有很多小图。

当我运行上述内容时,我会继续java.lang.OutOfMemoryError: Java heap space。我尝试使用executor-memory 32g并运行15个节点的集群,其中45g作为纱线容器大小。

以下是例外情况:

16/10/26 10:32:26 ERROR util.Utils: uncaught error in thread SparkListenerBus, stopping SparkContext
java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:2694)
    at java.lang.String.<init>(String.java:203)
    at java.lang.StringBuilder.toString(StringBuilder.java:405)
    at com.fasterxml.jackson.core.util.TextBuffer.contentsAsString(TextBuffer.java:360)
    at com.fasterxml.jackson.core.io.SegmentedStringWriter.getAndClear(SegmentedStringWriter.java:98)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2216)
    at org.json4s.jackson.JsonMethods$class.compact(JsonMethods.scala:32)
    at org.json4s.jackson.JsonMethods$.compact(JsonMethods.scala:44)
    at org.apache.spark.scheduler.EventLoggingListener$$anonfun$logEvent$1.apply(EventLoggingListener.scala:146)
    at org.apache.spark.scheduler.EventLoggingListener$$anonfun$logEvent$1.apply(EventLoggingListener.scala:146)
    at scala.Option.foreach(Option.scala:236)
    at org.apache.spark.scheduler.EventLoggingListener.logEvent(EventLoggingListener.scala:146)
    at org.apache.spark.scheduler.EventLoggingListener.onJobStart(EventLoggingListener.scala:173)
    at org.apache.spark.scheduler.SparkListenerBus$class.onPostEvent(SparkListenerBus.scala:34)
    at org.apache.spark.scheduler.LiveListenerBus.onPostEvent(LiveListenerBus.scala:31)
    at org.apache.spark.scheduler.LiveListenerBus.onPostEvent(LiveListenerBus.scala:31)
    at org.apache.spark.util.ListenerBus$class.postToAll(ListenerBus.scala:55)
    at org.apache.spark.util.AsynchronousListenerBus.postToAll(AsynchronousListenerBus.scala:37)
    at org.apache.spark.util.AsynchronousListenerBus$$anon$1$$anonfun$run$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(AsynchronousListenerBus.scala:80)
    at org.apache.spark.util.AsynchronousListenerBus$$anon$1$$anonfun$run$1$$anonfun$apply$mcV$sp$1.apply(AsynchronousListenerBus.scala:65)
    at org.apache.spark.util.AsynchronousListenerBus$$anon$1$$anonfun$run$1$$anonfun$apply$mcV$sp$1.apply(AsynchronousListenerBus.scala:65)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57)
    at org.apache.spark.util.AsynchronousListenerBus$$anon$1$$anonfun$run$1.apply$mcV$sp(AsynchronousListenerBus.scala:64)
    at org.apache.spark.util.Utils$.tryOrStopSparkContext(Utils.scala:1181)
    at org.apache.spark.util.AsynchronousListenerBus$$anon$1.run(AsynchronousListenerBus.scala:63)

此外,我收到了大量以下日志:

16/10/26 10:30:32 INFO spark.MapOutputTrackerMaster: Size of output statuses for shuffle 320 is 263 bytes
16/10/26 10:30:32 INFO spark.MapOutputTrackerMaster: Size of output statuses for shuffle 321 is 268 bytes
16/10/26 10:30:32 INFO spark.MapOutputTrackerMaster: Size of output statuses for shuffle 322 is 264 bytes

我的问题是,有没有人尝试过这种规模的ConnectedComponents?如果是的话,我做错了什么?

2 个答案:

答案 0 :(得分:3)

正如我在评论中发布的那样,我在Spark上使用map / reduce实现了连接组件。您可以在此处找到更多详细信息 - https://www.linkedin.com/pulse/connected-component-using-map-reduce-apache-spark-shirish-kumar以及MIT许可下的源代码 - https://github.com/kwartile/connected-component

答案 1 :(得分:2)

连通分量算法不能很好地扩展,其性能在很大程度上取决于图的拓扑结构。边缘的稀疏性并不意味着你有小的组件。一长串边缘非常稀疏(边数=顶点数 - 1),但GraphX中实现的暴力算法效率不高(参见ccpregel的来源)

以下是您可以尝试的内容(已排序,仅限代码):

  1. 在镶木地板(磁盘)上检查您的顶点和边缘,然后再次加载它们以构建图形。当执行计划变得太大时,缓存有时不会削减它。
  2. 以一种不会改变算法结果的方式转换图形。例如,您可以在code中看到算法正在向两个方向传播信息(默认情况下应如此)。因此,如果您有多条边连接相同的两个顶点,请从应用算法的图表中过滤掉它们。
  3. 自己优化GraphX代码(这非常简单),使用通用优化保存内存(即每次迭代时磁盘上的检查点以避免OOM),或域特定优化(类似于第2点)
  4. 如果你可以放弃GraphX(后来有些遗留),你可以考虑使用GraphFrames packageblog )。我从未尝试过,所以我不知道它是否有CC。

    我确信你可以在spark包中找到其他可能性,但也许你甚至想要使用Spark以外的东西。但这超出了问题的范围。

    祝你好运!