Як налаштувати номер виконавця іскри, ядра та пам’ять виконавця?


84

З чого ви починаєте налаштовувати вищезазначені параметри. Починаємо ми з пам'яті виконавця і отримуємо кількість виконавців, або починаємо з ядер і отримуємо номер виконавця. Я перейшов за посиланням . Однак отримав ідею високого рівня, але все ще не впевнений, як і з чого почати і дійти до остаточного висновку.

Відповіді:


206

Наступна відповідь охоплює 3 основні аспекти, згадані в назві - кількість виконавців, пам’ять виконавця та кількість ядер. Можуть бути й інші параметри, такі як пам'ять драйвера та інші, на які я не звертався на момент відповіді, але хотів би додати найближчим часом.

Випадок 1 Апаратне забезпечення - 6 вузлів, а кожен вузол - 16 ядер, 64 ГБ оперативної пам'яті

Кожен виконавець є екземпляром JVM. Отже, ми можемо мати декілька виконавців в одному Вузлі

Перше 1 ядро ​​та 1 ГБ потрібні для ОС та демонів Hadoop, тому доступні 15 ядер, 63 ГБ оперативної пам'яті для кожного вузла

Почніть з того, як вибрати кількість ядер :

Number of cores = Concurrent tasks as executor can run 

So we might think, more concurrent tasks for each executor will give better performance. But research shows that
any application with more than 5 concurrent tasks, would lead to bad show. So stick this to 5.

This number came from the ability of executor and not from how many cores a system has. So the number 5 stays same
even if you have double(32) cores in the CPU.

Кількість виконавців:

Coming back to next step, with 5 as cores per executor, and 15 as total available cores in one Node(CPU) - we come to 
3 executors per node.

So with 6 nodes, and 3 executors per node - we get 18 executors. Out of 18 we need 1 executor (java process) for AM in YARN we get 17 executors

This 17 is the number we give to spark using --num-executors while running from spark-submit shell command

Пам'ять для кожного виконавця:

From above step, we have 3 executors  per node. And available RAM is 63 GB

So memory for each executor is 63/3 = 21GB. 

However small overhead memory is also needed to determine the full memory request to YARN for each executor.
Formula for that over head is max(384, .07 * spark.executor.memory)

Calculating that overhead - .07 * 21 (Here 21 is calculated as above 63/3)
                            = 1.47

Since 1.47 GB > 384 MB, the over head is 1.47.
Take the above from each 21 above => 21 - 1.47 ~ 19 GB

So executor memory - 19 GB

Остаточні цифри - виконавці - 17, ядра 5, пам’ять виконавця - 19 Гб


Випадок 2 Апаратне забезпечення: Той самий 6 вузол, 32 ядра, 64 ГБ

5 однаково для хорошої паралельності

Кількість виконавців для кожного вузла = 32/5 ~ 6

Отже, загальна кількість виконавців = 6 * 6 Вузлів = 36. Тоді остаточне число - 36 - 1 для AM = 35

Пам'ять виконавця - це 6 виконавців для кожного вузла. 63/6 ~ 10. Над головою - 0,07 * 10 = 700 МБ. Отже, округлюючи до 1 Гб, як над головою, отримуємо 10-1 = 9 Гб

Остаточні цифри - виконавці - 35, ядра 5, пам’ять виконавця - 9 Гб


Випадок 3

Вищевказані сценарії починаються з прийняття кількості ядер як фіксованої та переміщення до # виконавців та пам'яті.

Тепер для першого випадку, якщо ми вважаємо, що нам не потрібно 19 ГБ, а достатньо лише 10 ГБ, то наступні цифри:

ядер 5 # виконавців для кожного вузла = 3

На цьому етапі це призведе до 21, а потім 19 згідно з нашим першим розрахунком. Але оскільки ми вважали, що 10 - це нормально (припустимо, мало накладних витрат), то ми не можемо переключити кількість виконавців на вузол на 6 (наприклад, 63/10). Окрім 6-ти виконавців на вузол і 5 ядер, воно зменшується до 30 ядер на вузол, коли у нас лише 16 ядер. Тож нам також потрібно змінити кількість ядер для кожного виконавця.

Отже, обчислюючи ще раз,

Чарівне число 5 приходить до 3 (будь-яке число менше або дорівнює 5). Отже, з 3 ядрами та 15 доступними ядрами - ми отримуємо 5 виконавців на вузол. Отже (5 * 6 -1) = 29 виконавців

Отже, пам’ять становить 63/5 ~ 12. Над головою - 12 * .07 = .84 Отже, пам’ять виконавця - 12 - 1 ГБ = 11 ГБ

Кінцеві номери - це 29 виконавців, 3 ядра, пам’ять виконавця - 11 Гб


Динамічний розподіл:

Примітка: Верхня межа кількості виконавців, якщо ввімкнено динамічне розподіл. Отже, це говорить про те, що програма іскр може з’їсти всі ресурси, якщо це потрібно. Тож у кластері, де у вас запущені інші програми, і їм також потрібні ядра для запуску завдань, будь ласка, переконайтесь, що ви робите це на рівні кластера. Я маю на увазі, що ви можете виділити певну кількість ядер для YARN на основі доступу користувачів. Таким чином, ви можете створити spark_user може бути, а потім дати ядра (мін / макс) для цього користувача. Ці обмеження призначені для спільного використання між іскрою та іншими програмами, які працюють на YARN.

spark.dynamicAllocation.enabled - Коли для цього встановлено значення true - нам не потрібно згадувати виконавців. Причина нижче:

Число статичних параметрів, яке ми надаємо при подачі іскри, стосується всієї тривалості роботи. Однак, якщо динамічне розподіл потрапляє в картину, існують різні етапи, подібні

З чого почати:

Початкова кількість виконавців ( spark.dynamicAllocation.initialExecutors ) для початку з

Скільки :

Потім на основі завантаження (очікуваних завдань), скільки запитувати. Зрештою це були б цифри, які ми даємо при іскровому поданні статичним способом. Отож, як тільки встановлені початкові номери виконавців, ми переходимо до мінімальних ( spark.dynamicAllocation.minExecutors ) та максимальних ( spark.dynamicAllocation.maxExecutors ) чисел.

Коли запитувати чи давати:

Коли ми запитуємо нових виконавців ( spark.dynamicAllocation.schedulerBacklogTimeout ) - Протягом такої тривалості було виконано завдання. так просимо. кількість виконавців, запитуваних у кожному турі, збільшується в геометричній прогресії порівняно з попереднім туром. Наприклад, програма додасть 1 виконавця в першому раунді, а потім 2, 4, 8 тощо, у наступних раундах. У певний момент вищезгаданий макс з’являється у картині

коли ми віддаємо виконавця ( spark.dynamicAllocation.executorIdleTimeout ) -

Будь ласка, виправте мене, якщо я щось пропустив. Вищезазначене я розумію на основі блогу, про який я поділився, та деяких Інтернет-ресурсів. Дякую.

Список літератури:


2
Я десь читав, що в автономному режимі лише один виконавець на вузол, будь-яка ідея щодо цього? Я не бачу цього у вашій відповіді.
jangorecki

2
В автономному кластері за замовчуванням ми отримуємо одного виконавця на кожного працівника. Нам потрібно грати з spark.executor.cores, і працівник має достатньо ядер, щоб отримати більше одного виконавця.
Рамзі,

Я виявив, що мій працівник використовує всі 32 ядра без налаштування spark.executor.cores, тому він може використовувати всі доступні за замовчуванням.
jangorecki

Так, за замовчуванням ядра нескінченні, як то кажуть. Отже, іскра може використовувати всі доступні ядра, якщо ви не вказали.
Рамзі,

2
@Ramzy Я думаю, що слід зазначити, що навіть при динамічному розподілі ви все одно повинні вказати spark.executor.cores, щоб визначити розмір кожного виконавця, який збирається виділити Spark. В іншому випадку, коли Spark збирається виділити нового виконавця у вашу програму, він виділить цілий вузол (якщо він доступний), навіть якщо все, що вам потрібно, це лише ще п'ять ядер.
Dan Markhasin

6

Крім того, важливим параметром конфігурації є:

spark.memory.fraction(Частка (простір купи - 300 МБ), що використовується для виконання та зберігання) з http://spark.apache.org/docs/latest/configuration.html#memory-management .

Якщо ви не використовуєте кеш / зберігати, встановіть його на 0,1, щоб у вас була вся пам’ять для вашої програми.

Якщо ви використовуєте кеш / персист, ви можете перевірити пам'ять, зайняту:

sc.getExecutorMemoryStatus.map(a => (a._2._1 - a._2._2)/(1024.0*1024*1024)).sum

Чи читаєте ви дані з HDFS або з HTTP?

Знову ж таки, налаштування залежить від вашого варіанту використання.


Чи знаєте ви, як би виглядала команда map під час використання pyspark? Я використовую sc._jsc.sc (). GetExecutorMemoryStatus (), щоб отримати статус виконавця, але нічого не можу зробити з тим, що повертає ...
Томас

1
Вибачте @Thomas Decaux , але ви мали на увазі налаштування spark.memory.storageFraction=0.1? Оскільки AFAIK spark.memory.fractionвирішує обсяг пам'яті, який використовується як Sparkдля виконання, так і для зберігання (про це ви вже згадали), і лише spark.memory.storageFractionпам'ять (доступна для зберігання + виконання) не захищена від вилучення кешу . Будь ласка, перегляньте це посилання
y2k-shubham

@Thomas Якщо в моїй заявці я маю лише persist (StorageLevel.DISK_ONLY), ніж цей параметр також застосовується, так? Він впливає лише на частку пам'яті, але не впливає на розливання диска?
jk1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.