Spark中有很多关于Task is not serializable
的问题。但是,这种情况似乎很特别。
我创建了一个类:
class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
val allEs: RDD[(String, E)] = e.map(e => (e.w, e))
.persist()
val sc = allEs.sparkContext
val centroids = sc.broadcast(m.clusterCenters)
[...]
该类定义了以下方法:
private def centroidDistances(v: Vector): Array[Double] = {
centroids.value.map(c => (centroids.value.indexOf(c), Vectors.sqdist(v, c)))
.sortBy(_._1)
.map(_._2)
}
但是,调用该类时,会抛出Task is not serializable
异常。
奇怪的是,类Neighbours
的标题中的微小变化足以解决问题。我没有创建用于广播的val sc: SparkContext
,而只是内联创建Spark上下文的代码:
class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
val allEs: RDD[(String, E)] = e.map(e => (e.w, e))
.setName("embeddings")
.persist()
val centroids = allEmbeddings.sparkContext(m.clusterCenters)
[...]
我的问题是:第二种变体如何产生影响?第一个出了什么问题?直觉上,这应该只是语法糖,这是Spark中的一个错误吗?
我在Hadoop / Yarn集群上使用Spark 1.4.1。
答案 0 :(得分:1)
定义时
class Neighbours(e: RDD[E], m: KMeansModel) extends Serializable {
...
val sc = allEmbeddings.sparkContext
val centroids = sc.broadcast(m.clusterCenters)
...
}
您已将sc
转换为类变量,这意味着可以从Neighbours
的实例访问它。 neighbours.sc
。这意味着sc
需要可序列化,但事实并非如此。
在内联代码时,只需要centroids
的最终值可序列化。 centroids
的类型为Broadcast
,可序列化。