Graphx:我在mapVertices中有NullPointerException

时间:2014-09-23 14:21:19

标签: scala apache-spark

我想使用graphx。现在我只是在本地推出它。 我在这几行中得到了NullPointerException。第一个println工作正常,第二个打印失败。

..........
val graph: Graph[Int, Int] = Graph(users, relationships)
println("graph.inDegrees = " + graph.inDegrees.count) // this line works well
graph.mapVertices((id, v) => {
  println("graph.inDegrees = " + graph.inDegrees.count) // but this one fails
  42 // doesn't mean anything
}).vertices.collect

我调用的'graph'对象的哪种方法无关紧要。但'mapVertices'中的'graph'不为空。

Exception failure in TID 2 on host localhost: 
java.lang.NullPointerException
org.apache.spark.graphx.impl.GraphImpl.mapReduceTriplets(GraphImpl.scala:168)
org.apache.spark.graphx.GraphOps.degreesRDD(GraphOps.scala:72)
org.apache.spark.graphx.GraphOps.inDegrees$lzycompute(GraphOps.scala:49)
org.apache.spark.graphx.GraphOps.inDegrees(GraphOps.scala:48)
ololo.MyOwnObject$$anonfun$main$1.apply$mcIJI$sp(Twitter.scala:42)

2 个答案:

答案 0 :(得分:2)

在Spark 1.0.2上使用GraphX 2.10重现。我会给你一个解决方法,然后解释我的想法。这对我有用:

val c = graph.inDegrees.count
graph.mapVertices((id, v) => {
  println("graph.inDegrees = " + c)
}).vertices.collect

通常,当您尝试在单个分区上并行执行的代码中访问整个RDD或其他分布式对象(如Graph)时,Spark会变得棘手,就像你传递给mapVertices的功能一样。但即使你可以让它发挥作用,它通常也是一个坏主意。 (作为一个单独的问题,正如您所见,当它不起作用时,往往会导致无用的行为。)

Graph的顶点表示为RDD,并且传递给mapVertices的函数在适当的分区中本地运行,在该分区中可以访问本地顶点数据: idv。您真的不希望将整个图表复制到每个分区。在这种情况下,您只需要向每个分区广播一个标量,因此将其拉出来解决了问题并且广播非常便宜。

Spark API中有一些技巧可以在这种情况下访问更复杂的对象,但如果你不小心使用它们,它们会破坏你的性能,因为它们往往会引入大量的通信。人们常常倾向于使用它们,因为他们不了解计算模型,而不是因为他们确实需要,尽管确实也会这样。

答案 1 :(得分:1)

Spark不支持嵌套RDD或引用其他RDD的用户定义函数,因此NullPointerException;见this thread on the spark-users mailing list。在这种情况下,您尝试从count()转换内部Graph(对Spark RDD执行操作)调用mapVertices(),导致NullPointerException mapVertices()尝试访问只能由Spark驱动程序调用的数据结构。

简而言之,只有Spark驱动程序可以启动新的Spark作业;你不能从其他RDD动作中调用对RDD的动作。

有关此问题的另一个示例,请参阅https://stackoverflow.com/a/23793399/590203