Повышение производительности для функции, которая подсчитывает общие слова

#scala #apache-spark

#scala #apache-spark

Вопрос:

У меня есть эта программа, которая использует Apache Spark для вычисления частоты слов.

Я создаю RDD с парами ключ / значение (слово = ключ, частота = значение). Набор данных распределяется по рабочим узлам. Функция frequentWordCount выполняется через регулярные промежутки времени. Она выбирает строки из файлов. которые затем преобразуются в пары ключ-значение и подключаются к wordDataset-RDD. Подсчитываются слова с частотой >50.

Мне сказали, что этот подход неэффективен. Может кто-нибудь сказать мне, почему и как я мог бы это улучшить?

 val sc = new SparkContext(...)
var wordDataset:RDD[(String, Int)] = sc.sequenceFile[String, Int](“…”).persist()

def frequentWordCount(fileName:String):Long = {
   val words = sc.sequenceFile[String](fileName)
   val joined = wordDataset.join(words.map(x=>(x,1)))
   joined.filter(x=>x._1._2>50).count
}
  

Ответ №1:

Примерно сколько частых слов у вас будет? Для множества разумных задач, я думаю, она должна быть неожиданно маленькой — достаточно маленькой, чтобы поместиться в памяти каждого отдельного компьютера. IIRC, слова, как правило, подчиняются степенному распределению, поэтому не должно быть так много «общих» слов. В этом случае трансляция набора часто встречающихся слов может быть намного быстрее, чем объединение:

 val sc = new SparkContext(...)
var commonWords: BroadCast[Set[String]] = sc.broadcast(sc.sequenceFile[String, Int](“…”).filter(_._2 > 50).collect().toSet)

def frequentWordCount(fileName:String):Long = {
   val words = sc.sequenceFile[String](fileName)
   words.filter(commonWords.value.contains).count
}
  

Если вы вызываете frequentWordCount несколько раз, вероятно, также лучше сделать это всего за одну операцию RDD, где ваши слова связаны с именем файла, а затем сгруппированы и подсчитаны или что-то в этом роде … особенности зависят от того, как это используется.

Комментарии:

1. Спасибо за ответ. Изменится ли что-нибудь, если количество часто встречающихся слов увеличится до 10 тысяч?

2. 10 тысяч слов? Это мелочи. Скажем, в среднем 10 символов на слово, 20 байт, плюс любые накладные расходы, скажем, 50 байт. Это примерно половина Мег …

3. Итак, не было бы никакого способа?

Ответ №2:

Если количество общих слов достаточно мало, чтобы поместиться в памяти Set , то, что предлагает другой ответ (за исключением того, что вам нужно map(_._1) там после filter .

В противном случае, две вещи, которые вы могли бы улучшить, — это (1) фильтровать перед объединением, вы хотите выбросить дополнительные данные как можно скорее, а не сканировать их несколько раз без необходимости, и (2) как правило, вы всегда хотите присоединять больший набор данных к меньшему, а не наоборот.

  sc.sequenceFile[String](fileName)
   .keyBy(identity)
   .join(wordDataset.filter(_._2 > 50))
   .count