Определение оптимального количества разделов Spark на основе рабочих, ядер и размера DataFrame

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

  • Драйвер Spark node (sparkDriverCount)
  • Число рабочих узлов, доступных для Spark-кластера (numWorkerNodes)
  • Число исполнителей Spark (numExecutors)
  • DataFrame управляется всеми рабочими/исполнителями одновременно (dataFrame)
  • Число строк в dataFrame (numDFRows)
  • Число разделов на dataFrame (numPartitions)
  • И, наконец, количество ядер процессора, доступных на каждом рабочем узле (numCpuCoresPerWorker)

Я считаю, что все Spark-кластеры имеют один и только один Spark Driver, а затем 0+ рабочих узлов. Если я ошибаюсь, начните с исправления! Предполагая, что я более или менее корректен в этом вопросе, позвольте заблокировать здесь несколько переменных. Скажем, у нас есть Spark-кластер с 1 драйвером и 4 рабочими узлами, и каждый Worker node имеет на нем 4 ядра процессора (так что в общей сложности 16 ядер процессора). Итак, "данный" здесь:

sparkDriverCount = 1
numWorkerNodes = 4
numCpuCores = numWorkerNodes * numCpuCoresPerWorker = 4 * 4 = 16

Учитывая, что в качестве настройки мне интересно, как определить несколько вещей. В частности:

  • Какова связь между numWorkerNodes и numExecutors? Существует ли известное/общепринятое отношение работников к исполнителям? Есть ли способ определить numExecutors с учетом numWorkerNodes (или любых других входов)?
  • Существует ли известное/общепринятое/оптимальное отношение numDFRows to numPartitions? Как вычислить "оптимальное" количество разделов на основе размера dataFrame?
  • Я слышал от других инженеров, что общее "эмпирическое правило": numPartitions = numWorkerNodes * numCpuCoresPerWorker, любая правда к этому? Другими словами, он предписывает, что для каждого ядра процессора должен быть 1 раздел.

Ответ 1

Да, приложение имеет один и только драйвер.

Какова связь между numWorkerNodes и numExecutors?

Работник может размещать несколько исполнителей, вы можете думать о нем, как о рабочем, как о машине / node вашего кластера, а исполнитель должен быть процессом (выполняющим в ядре), который выполняется на этом рабочем месте.

Итак, `numWorkerNodes <= numExecutors '.

Есть ли у них рацион?

Лично, работая в поддельном кластере, где моим ноутбуком был Драйвер, а виртуальная машина на том же ноутбуке была рабочим, а в промышленном кластере из > 10 тыс. узлов мне не нужно было заботиться об этом, так как кажется, что позаботится что.

Я просто использую:

--num-executors 64

когда я запускаю/отправляю свои script и знает, я думаю, сколько рабочих нужно вызвать (конечно, учитывая другие параметры, а также характер машин).

Таким образом, лично я не знаю такого отношения.


Существует ли известное/общепринятое/оптимальное отношение от numDFRows до numPartitions?

Я не знаю об этом, но, как правило, вы можете положиться на произведение #executors на # executor.cores, а затем умножить его на 3 или 4. Конечно, это эвристика. В он будет выглядеть так:

sc = SparkContext(appName = "smeeb-App")
total_cores = int(sc._conf.get('spark.executor.instances')) * int(sc._conf.get('spark.executor.cores'))
dataset = sc.textFile(input_path, total_cores * 3)

Как рассчитывается "оптимальное" количество разделов на основе размера DataFrame?

Это отличный вопрос. Конечно, трудно ответить, и это зависит от ваших данных, кластера и т.д., Но, как обсуждалось здесь с собой.

Слишком мало разделов, и у вас будут огромные куски данных, особенно когда вы имеете дело с , тем самым помещая ваше приложение в стресс.

Слишком много разделов, и у вас будет hdfs требует большого давления, поскольку все метаданные, которые должны быть сгенерированы из значительно увеличивается по мере увеличения количества разделов (поскольку он поддерживает временные файлы и т.д.). *

Так что вы хотите найти слишком сладкое место для количества разделов, что является одной из частей тонкой настройки вашего приложения.:)

'правило: numPartitions = numWorkerNodes * numCpuCoresPerWorker, это правда?

А, я писал эвристику выше, прежде чем увидеть это. Так что это уже ответили, но учтите разницу между работником и исполнителем.


* Я просто не справился сегодня: Подготовьте мои bigdata с помощью Spark через Python, когда используется слишком много разделов, вызванных Активные задачи - это отрицательное число в пользовательском интерфейсе Spark.