Наступна відповідь охоплює 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 ) -
Будь ласка, виправте мене, якщо я щось пропустив. Вищезазначене я розумію на основі блогу, про який я поділився, та деяких Інтернет-ресурсів. Дякую.
Список літератури: