Apache spark org.apache.spark.SparkException:任务不可序列化-使用参数时

Apache spark org.apache.spark.SparkException:任务不可序列化-使用参数时,apache-spark,rdd,Apache Spark,Rdd,尝试在映射中使用输入参数时,我收到一个任务不可序列化的错误: val errors = inputRDD.map { case (itemid, itemVector, userid, userVector, rating) => (itemid, itemVector, userid, userVector, rating, ( (rating - userVector.dot(itemVector)) * itemVector

尝试在
映射中使用输入参数时,我收到一个
任务不可序列化的
错误:

val errors = inputRDD.map { 
    case (itemid, itemVector, userid, userVector, rating) =>
    (itemid, itemVector, userid, userVector, rating, 
        (
            (rating - userVector.dot(itemVector)) * itemVector) 
            - h4 * userVector
        )
    }
我将
h4
与类的参数一起传入

map
是一种方法,如果在
map
转换之前,我输入了以下内容,则它可以正常工作:

val h4 = h4

如果我不这样做,或者把它放在方法之外,那么它就不工作了,我得到了
任务不可序列化
。为什么会发生这种情况?我为方法外部的类生成的其他
val
在方法内部工作,那么当从输入参数/参数实例化
val
时,它为什么没有呢?

错误表明
h4
所属的类不可序列化

下面是一个类似的例子:

class ABC(h: Int) { 
  def test(s:SparkContext) = s.parallelize(0 to 5).filter(_ > h).collect 
}

new ABC(3).test(sc)
//org.apache.spark.SparkException: Job aborted due to stage failure: 
//    Task not serializable: java.io.NotSerializableException: 
//    $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$ABC
当在rdd转换中使用
this.h
时,
this
将成为序列化的闭包的一部分

使类可序列化按预期工作:

class ABC(h: Int) extends Serializable { 
  def test(s:SparkContext) = s.parallelize(0 to 5).filter(_ > h).collect
}

new ABC(3).test(sc)
// Array[Int] = Array(4, 5)
通过在方法中定义局部变量,在rdd转换中删除对该
的引用也是如此:

class ABC(h: Int) { 
  def test(s:SparkContext) = { 
      val x = h;
      s.parallelize(0 to 5).filter(_ > x).collect 
  }
}

new ABC(3).test(sc)
// Array[Int] = Array(4, 5)

您可以使用广播变量。它将变量中的数据广播给所有工作人员。有关更多详细信息,请访问此项。

h4
是在单独的类中声明的变量吗?如果是,则尝试从可序列化接口扩展该类。h4是什么类型?它是可序列化的吗?
h4
是在类中声明的,并且是Double吗?我的印象是
Double
是可序列化的
h4
是一个
Double
。还有什么想法吗?谢谢@monster是的,Double是可序列化的,
h4
是Double。要点是:它是一个类的成员,因此
h4
this.h4
的缩写,其中
this
指的是类的对象。当使用
this.h4
时,
被拉入序列化的闭包中,因此需要使类可序列化;而且,这都是在一个类。这有区别吗?@monster
val errors
h4
是同一类的成员(它扩展了可序列化的
)@monster在这种情况下,该类可能包含一些其他不可序列化的成员。