Я смотрел документацию на искру, и он упоминает это:
API Sparks в значительной степени зависит от передачи функций в программе драйвера для запуска в кластере. Существует два рекомендуемых способа:
Анонимный синтаксис функций, который можно использовать для коротких фрагментов кода. Статические методы в глобальном одноэлементном объекте. Например, вы можете определить объект MyFunctions, а затем передать MyFunctions.func1 следующим образом:
object MyFunctions { def func1(s: String): String = { ... } }
myRdd.map(MyFunctions.func1)
Обратите внимание, что, хотя также возможно передать ссылку на метод в экземпляре класса (в отличие от singleton object), это требует отправки объекта, который содержит класса вместе с методом. Например, рассмотрим:
class MyClass {
def func1(s: String): String = { ... }
def doStuff(rdd: RDD[String]): RDD[String] = { rdd.map(func1) }
}
Здесь, если мы создадим новый MyClass и назовите doStuff на нем, карта внутри ссылается на метод func1 этого экземпляра MyClass, поэтому весь объект должен быть отправлен в кластер. Это похоже на запись
rdd.map(x => this.func1(x))
.
Теперь мое сомнение в том, что произойдет, если у вас есть атрибуты для объекта singleton (которые должны быть эквивалентны статическому). Тот же пример с небольшим изменением:
object MyClass {
val value = 1
def func1(s: String): String = { s + value }
}
myRdd.map(MyClass.func1)
Таким образом, функция все еще ссылается статически, но насколько далеко продвигается Spark, пытаясь сериализовать все ссылочные переменные? Будет ли он сериализоваться value
или он будет снова инициализирован удаленными сотрудниками?
Кроме того, это все в контексте, что у меня есть некоторые тяжелые модели внутри одного объекта, и я хотел бы найти правильный способ сериализации их для рабочих, сохраняя возможность ссылаться на них из синглтона повсюду, а не на передачу их вокруг как функциональные параметры в довольно глубоком стеке вызовов функций.
Любая подробная информация о том, что/как/когда делает сериализацию Spark, будет оценена.