Spark RDD / DF как переменный член класса. Влияет ли это на производительность? - PullRequest
0 голосов
/ 06 ноября 2018

Я хотел бы задать один теоретический вопрос.

Представьте, что у нас есть наш главный объект как:

val pathToFile: String = "/some/path/to/file.csv" 
val rddLoader: RddLoader = new RddLoader(pathToFile)
val rdd = rddLoader.load()
def transformer = new Transformer(rdd)
transformer.transform1(someOtherRdd)
transformer.transform2(yetAnotherRdd)

И выход трансформатора определяется как (псевдокод)

class Transformed(rdd: RDD[sruct]) {

  val rddToTransform = rdd.someTransformation

  def complexTransformations1(anotherRdd: RDD[struct]) = {
     rddToTransform.complexTransformationsInvlovingAnotherRdd
  }

  def complexTransformations2(anotherRdd: RDD[struct]) = {
     rddToTransform.complexTransformations2InvlovingAnotherRdd
  }
}

Будет ли влиять тот факт, что rddToTransfrom является членом класса и, следовательно, членом экземпляра класса, повлияет на производительность. Я думаю, что весь класс будет сериализован. Но приведет ли это к тому, что rddToTransform будет сериализован для каждого раздела, таким образом, несколько раз.

Будет ли приведенное ниже описание с точки зрения производительности, сериализации служебных данных и т. Д. В нем мы используем объект, а наш СДР не является членом класса, а просто передается в качестве параметра методу.

val pathToFile: String = "/some/path/to/file.csv" 
val rddLoader: RddLoader = new RddLoader(pathToFile)
val rdd = rddLoader.load()
def transformer = Transformer
transformer.transform1(rdd, someOtherRdd)
transformer.transform2(rdd, yetAnotherRdd)


object Transformer {

  def complexTransformations1(rdd, anotherRdd: RDD[struct]) = {
     rddToTransform.complexTransformationsInvlovingAnotherRdd
  }

  def complexTransformations2(rdd, anotherRdd: RDD[struct]) = {
     rddToTransform.complexTransformations2InvlovingAnotherRdd
  }
}

Я могу привести пример с широковещательными переменными. Я понимаю их способ работы. Мне просто интересно, будет ли то, что объясняется ниже, применимо также к СДР и нужно ли нам избегать использования СДР, как в первом примере (член класса)

Допустим, у нас есть большой набор данных с 420 разделами и кластером из 8 узлов-исполнителей. В операции, как:

val referenceData = Map(...)
val filtered = rdd.filter(elem => referenceData.get(elem) > 10)

Объект referenceData будет сериализован 420 раз, или столько задач, сколько требуется для выполнения преобразования.

Вместо этого широковещательная переменная:

val referenceDataBC = sparkContext.broadcast(Map(...))
val filtered = rdd.filter(elem => referenceDataBC.value.get(elem) > 10)

будет отправлено одному исполнителю или 8 раз. Следовательно, экономя много сети и ЦП, уменьшая издержки сериализации.

1 Ответ

0 голосов
/ 06 ноября 2018

Короткий ответ - да, в обычных случаях широковещательные переменные лучше оптимизируют память, но есть случаи, когда они не могут использоваться.

Чтобы лучше понять:

Apache Spark имеет два типа абстракций. Основная абстракция, которую предоставляет Spark, - это Эластичный распределенный набор данных (RDD), а другой - Shared Variables.

Общие переменные: Общие переменные - это переменные, которые должны использоваться многими функциями и методами параллельно. Общие переменные могут использоваться в параллельных операциях.

Spark разделяет задание на наименьшую возможную операцию - замыкание, выполняемое на разных узлах и каждое из которых имеет копию всех переменных задания Spark. Любые изменения, внесенные в эти переменные, не отражаются в программе драйвера и, следовательно, для преодоления этого ограничения Spark предоставляет два специальных типа общих переменных - переменные широковещательной передачи и аккумуляторы.

переменные вещания: Используется для кэширования значения в памяти на всех узлах. Здесь только один экземпляр этой переменной только для чтения используется всеми вычислениями в кластере. Spark отправляет широковещательную переменную каждому узлу, связанному с соответствующей задачей. После этого каждый узел кэширует его локально в сериализованной форме. Теперь перед выполнением каждой из запланированных задач вместо получения значений из системы драйверов извлекает их локально из кэша. Вещательные переменные:

Неизменный (неизменяемый), Распространяется, т.е. транслируется в кластер, Вписывается в память

Аккумуляторы: Как следует из названия, основная роль Аккумуляторов заключается в накоплении ценностей. Аккумулятор - это переменные, которые используются для реализации счетчиков и сумм. Spark предоставляет аккумуляторы только числового типа. Пользователь может создавать именованные или безымянные аккумуляторы. В отличие от Broadcast Variables, аккумуляторы доступны для записи. Однако записанные значения могут быть прочитаны только в программе драйвера. Вот почему аккумуляторы работают так же хорошо, как агрегаторы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...