我想使用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)
答案 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
的函数在适当的分区中本地运行,在该分区中可以访问本地顶点数据: id
和v
。您真的不希望将整个图表复制到每个分区。在这种情况下,您只需要向每个分区广播一个标量,因此将其拉出来解决了问题并且广播非常便宜。
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。