gpt4 book ai didi

scala - 方法参数是否触发 Spark 中的序列化?

转载 作者:行者123 更新时间:2023-12-04 13:20:14 25 4
gpt4 key购买 nike

我读了Spark programming guide关于传递函数,想知道当函数引用外部方法参数/局部变量时会发生什么。

比如我有这个对象

object Main {
def main(args: Array[String]): Unit = {
val ds: Dataset[String] = ???
ds.map(_ + args(0))
}
}

Spark 是否必须序列化 Main?如果 argsmain 中的局部变量怎么办?

最佳答案

不,在这两种情况下,Spark 都不会序列化 Main 对象。方法参数和局部变量(从语义的角度来看几乎是同一件事)不“属于”封闭对象或类,它们与特定方法调用相关联,因此可以直接由闭包捕获。

作为一般规则,如果您需要引用某个对象以访问某个值,那么该引用将被捕获并因此被序列化:

class Application(n: Int) {
val x = "internal state " + n

def doSomething(ds: Dataset[String], param: String): Unit = {
ds.map(_ + x + param)
}
}

请注意,这里为了访问x,它是一个实例成员,您必须要有可用的封闭实例,因为它取决于实际构造实例的参数。另一种看待它的方法是记住当你在上面的例子中使用 x 时,它实际上是 this.x 的快捷方式:

ds.map(_ + this.x + param)

与此相比,param 值没有这种依赖性 - 它按原样传递给方法,无需访问任何其他封闭对象即可使用它。因此,param会被直接捕获并序列化。

这就是为什么有人建议将实例成员放入局部变量,以免捕获整个对象:当您将值放入局部变量时,它不再需要访问封闭的实例:

val localX = this.x
ds.map(_ + localX + param)

当然,如果您引用了要捕获的对象内部的封闭实例,如下所示:

class Inner(app: Application)

class Application {
val x = new Inner(this)

def doSomething(ds: Dataset[String]): Unit = {
val localX = x
ds.map(_ + localX.toString)
}
}

然后将其存储到局部变量中也无济于事,因为 Spark 仍需要序列化 ​​Inner 类的 app 字段,它指向回 应用 实例。这就是为什么如果您在 Spark 方法中使用要发送给执行程序的复杂对象图,则必须小心。

关于scala - 方法参数是否触发 Spark 中的序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53881550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com