Apache Spark: кількість ядер проти кількості виконавців


194

Я намагаюся зрозуміти взаємозв'язок кількості ядер та кількості виконавців під час виконання завдання Spark на YARN.

Тестове середовище таке:

  • Кількість вузлів даних: 3
  • Технічні характеристики вузла даних:
    • Процесор: Core i7-4790 (кількість ядер: 4, кількість потоків: 8)
    • ОЗУ: 32 ГБ (8 ГБ х 4)
    • Жорсткий диск: 8 ТБ (2 ТБ х 4)
  • Мережа: 1 Гбіт

  • Версія іскри: 1.0.0

  • Версія Hadoop: 2.4.0 (Hortonworks HDP 2.1)

  • Іскровий потік завдань: sc.textFile -> фільтр -> карта -> фільтр -> mapToPair -> зменшитиByKey -> карта -> saveAsTextFile

  • Вхідні дані

    • Тип: єдиний текстовий файл
    • Розмір: 165GB
    • Кількість рядків: 454,568,833
  • Вихідні дані

    • Кількість рядків після другого фільтра: 310,640,717
    • Кількість рядків файлу результатів: 99,848,268
    • Розмір файлу результатів: 41 Гб

Завдання виконувались із такими конфігураціями:

  1. --master yarn-client --executor-memory 19G --executor-cores 7 --num-executors 3 (виконавці на вузол даних, використовувати стільки, скільки ядер)

  2. --master yarn-client --executor-memory 19G --executor-cores 4 --num-executors 3 (зменшено кількість ядер)

  3. --master yarn-client --executor-memory 4G --executor-cores 2 --num-executors 12 (менше ядра, більше виконавця)

Закінчені часи:

  1. 50 хв 15 сек

  2. 55 хв 48 сек

  3. 31 хв 23 сек

На мій подив, (3) був набагато швидшим.
Я подумав, що (1) буде швидше, оскільки між переміщенням між виконавцями буде менше спілкування.
Хоча кількість ядер (1) менше (3), #of ядер не є ключовим фактором, оскільки 2) спрацювали добре.

(Дописи додано після відповіді pwilmot.)

Для інформації захоплення екрана монітора продуктивності виглядає наступним чином:

  • Підсумок вузла даних Ganglia для (1) - робота розпочата о 04:37.

Підсумок вузлів даних Ganglia для (1)

  • Підсумок вузла даних Ganglia для (3) - робота розпочата о 19:47. Будь ласка, ігноруйте графік до цього часу.

Підсумок вузлів даних Ganglia для (3)

Графік приблизно розділений на 2 розділи:

  • По-перше: від запуску до зниженняByKey: процесор інтенсивний, відсутність мережевої активності
  • По-друге: після reduByKey: процесор знижується, мережевий ввод-вивід робиться.

Як показує графік, (1) може використовувати стільки потужностей процесора, скільки було дано. Отже, це може бути не проблема кількості потоків.

Як пояснити цей результат?


2
Зараз я підозрюю GC ... Насправді в Spark UI загальний час, витрачений на GC, більше на 1), ніж на 2).
zeodtr

Чому ви не спробували 3) з 19G? Чи може бути, що обмеження працівників на 4G зменшує ефект NUMA, який має місце у деяких ppl? тобто ваш 4G розташований на одному з 2 ядер, виділених на ваш робочий процес, і, таким чином, відбувається менше сповільнення вводу-виводу, що призводить до кращих загальних показників. В іншому випадку я думаю, що головне питання: скільки ядер / ниток може використовувати один виконавець на працівнику? (Можна вказати лише загальну кількість сердечників для працівника, а не за деталізацією виконавця)
Бекон

5
До речі, я щойно перевірив код на core / src / main / scala / org / apache / spark / розвідник / розгортання / робочий / ExecutorRunner.scala, і здається, що 1 виконавець = 1 робоча нитка.
Бекон

трохи пізно, але ось допис про cloudera на цю тему: blog.cloudera.com/blog/2015/03/…
Орелус

1
До речі, я знайшов цю інформацію в колоді слайдів cloudera slideshare.net/cloudera/… , що пояснює трохи про прийняття рішень у виконавців, ядер та пам'яті
Manish Sahni

Відповіді:


58

Для того, щоб сподіватися, що все це трохи конкретніше, ось розроблений приклад налаштування програми Spark для використання якомога більшої частини кластеру: Уявіть кластер із шістьма вузлами, на яких працює NodeManagers, кожен обладнаний 16 ядрами та 64 ГБ пам’яті . Потужність NodeManager, yarn.nodemanager.resource.memory-mb та yarn.nodemanager.resource.cpu-vcores, ймовірно, повинна бути встановлена ​​на 63 * 1024 = 64512 (мегабайт) і 15 відповідно. Ми уникаємо виділяти 100% ресурсів на контейнери YARN, оскільки вузол потребує певних ресурсів для запуску демонів ОС і Hadoop. У цьому випадку ми залишаємо гігабайт і ядро ​​для цих системних процесів. Менеджер Cloudera допомагає, обробляючи їх та автоматично налаштовуючи ці властивості ПРИКОРОСТІ.

Найімовірнішим першим імпульсом було б використання - число-виконавці 6 - виконавці-сердечники 15 - екзекутор-пам'ять 63G . Однак це неправильний підхід, оскільки:

63 ГБ + накладні витрати на пам'ять виконавця не помістяться в межах 63 Гб NodeManagers. Мастер додатків займе ядро ​​на одному з вузлів, що означає, що на цьому вузлі не буде місця для 15-ядерного виконавця. 15 ядер на виконавця можуть призвести до поганої пропускної здатності вводу / виводу HDFS.

Кращим варіантом буде використання --num-execitors 17 --executor-cores 5 --executor-memory 19G . Чому?

Ця конфігурація призводить до трьох виконавців на всіх вузлах, крім одного з AM, у якого будуть два виконавці. --executor-memory отримано як (63/3 виконавців на вузол) = 21. 21 * 0,07 = 1,47. 21 - 1,47 ~ 19.

Пояснення було дано у статті в блозі Cloudera, як робити: Налаштуйте роботу Apache Spark (частина 2) .


1
"Ця конфігурація призводить до трьох виконавців на всіх вузлах, крім одного з AM, який матиме двох виконавців." Що це означає щодо "--executor-cores 5"?
дерек

Це означає, що кожен виконавець використовує 5 ядер. Кожен вузол має 3 виконавців, тому використовуючи 15 ядер, за винятком того, що один із вузлів також запускає майстер додатків для завдання, тому він може розміщувати лише 2 виконавця, тобто 10 ядер, які використовуються як виконавці.
Давос

Чудово пояснено - зверніть увагу, що це стосується yarn.scheduler.capacity.resource-calculatorінвалідів, що є типовим. Це тому, що за замовчуванням він планує пам'ять, а не процесор.
YoYo

1
Більше виконавців може призвести до поганої пропускної здатності вводу / виводу HDFS. Тож якщо я взагалі не використовую HDFS, чи можу я використовувати більше 5 ядер на виконавця?
Даршан

Я, хоча майстер програм працює на кожному Вузлі. Згідно вище, це означає, що для запуску завдання буде лише 1 майстер додатків. Це правильно?
Рошан Фернандо

15

Під час запуску іскрового додатка на вершині HDFS, повідомляє Sandy Ryza

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

Тому я вважаю, що ваша перша конфігурація повільніше, ніж третя, через погану пропускну здатність HDFS вводу / виводу


11

Я сам не грав з цими налаштуваннями, тому це лише спекуляція, але якщо ми розглянемо цю проблему як звичайні ядра та потоки в розподіленій системі, то у вашому кластері ви можете використовувати до 12 ядер (4 * 3 машини) та 24 потоків (8 * 3 машини). У своїх перших двох прикладах ви даєте своїй роботі неабияку кількість ядер (потенційний обчислювальний простір), але кількість потоків (завдань) для запуску на цих ядрах настільки обмежена, що ви не можете використовувати велику частину виділеної потужності обробки і, отже, робота проходить повільніше, хоча виділено більше обчислювальних ресурсів.

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


Дякую за вашу відповідь. Але я підозрюю, що кількість ниток не є основною проблемою. Я додав знімок екрана моніторингу. Як показує графік, 1) може використовувати стільки потужностей процесора, скільки було дано.
zeodtr

1
@zeodtr pwilmot правильний - вам потрібно 2-4 завдання МІНІМУМ, щоб використати весь потенціал ваших ядер. Скажімо так: я зазвичай використовую принаймні 1000 розділів для мого 80 ядерного кластера.
samthebest

@samthebest Те, що я хочу знати, є причиною різниці в продуктивності між 1) і 3). Коли я спостерігаю за Spark UI, обидва виконують 21 завдання паралельно у розділі 2. (чому 21 замість 24 у випадку 3) наразі невідомо) Але завдання для 3) просто працює швидше.
zeodtr

10

Коротка відповідь : Я думаю, що tgbaggio є правильним. Ви досягаєте обмежень пропускної здатності HDFS на своїх виконавців.

Я думаю, що відповідь тут може бути трохи простішим, ніж деякі рекомендації тут.

Підказки для мене є в графіку мережі кластерів. Для виконання 1 коефіцієнт використання стабільний на рівні ~ 50 М байт / с. Для запуску 3 стабільне використання збільшується вдвічі, близько 100 М байт / с.

З публікації блогу cloudera , яку поділився DzOrd , ви можете побачити цю важливу цитату:

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

Отже, давайте зробимо кілька розрахунків, щоб побачити, яку ефективність ми очікуємо, якщо це правда.


Виконати 1: 19 ГБ, 7 ядер, 3 виконавці

  • 3 виконавці х 7 ниток = 21 нитка
  • з 7 ядрами на одного виконавця, ми очікуємо обмеженого IO до HDFS (максимум на ~ 5 ядер)
  • ефективна пропускна здатність ~ = 3 виконавця х 5 ниток = 15 ниток

Виконати 3: 4 ГБ, 2 ядра, 12 виконавців

  • 2 виконавці х 12 ниток = 24 нитки
  • 2 ядра на виконавця, тому пропускна здатність hdfs нормальна
  • ефективна пропускна здатність ~ = 12 виконавців х 2 нитки = 24 нитки

Якщо завдання на 100% обмежене одночасністю (кількістю ниток). Ми очікуємо, що час виконання буде повністю обернено співвідноситься з кількістю потоків.

ratio_num_threads = nthread_job1 / nthread_job3 = 15/24 = 0.625
inv_ratio_runtime = 1/(duration_job1 / duration_job3) = 1/(50/31) = 31/50 = 0.62

Отже ratio_num_threads ~= inv_ratio_runtime, і, схоже, ми обмежені в мережі.

Цей же ефект пояснює різницю між запуском 1 та запуском 2.


Виконати 2: 19 ГБ, 4 сердечники, 3 виконавці

  • 3 виконавці х 4 нитки = 12 ниток
  • з 4 ядрами на одного виконавця, нормально IO для HDFS
  • ефективна пропускна здатність ~ = 3 виконавця х 4 нитки = 12 ниток

Порівнюючи кількість ефективних потоків та час виконання:

ratio_num_threads = nthread_job2 / nthread_job1 = 12/15 = 0.8
inv_ratio_runtime = 1/(duration_job2 / duration_job1) = 1/(55/50) = 50/55 = 0.91

Це не так ідеально, як останнє порівняння, але ми все одно спостерігаємо подібне зниження продуктивності, коли втрачаємо теми.

Тепер для останнього шматочка: чому це так, що ми отримуємо кращі показники з більшою кількістю потоків, особливо. більше потоків, ніж кількість процесорів?

Хороше пояснення різниці між паралелізмом (що ми отримуємо, розділивши дані на декілька процесорів) та паралельністю (що ми отримуємо, коли використовуємо декілька потоків для роботи над одним процесором), надається в цьому чудовому дописі Робом Пайком: Concurrency не є паралелізмом .

Коротке пояснення полягає в тому, що якщо Spark завдання взаємодіє з файловою системою або мережею, процесор витрачає багато часу на очікування спілкування з цими інтерфейсами і не витрачаючи багато часу, фактично "виконуючи роботу". Давши цим процесорам більше, ніж одне завдання, над яким можна працювати, вони витрачають менше часу на очікування і більше часу на роботу, і ви бачите кращу ефективність.


1
Цікаве та переконливе пояснення, мені цікаво, як ви придумали, що у виконавця є 5 меж завдань для досягнення максимальної пропускної здатності.
Дат Нгуен

Таким чином, число 5 не те, що я придумав: я щойно помітив ознаки вузького зменшення вугілля і пішов шукати, звідки вони можуть з’явитися.
turtlemonvh

8

З чудових ресурсів, доступних на сторінці пакета RStudio Sparklyr :

ВИЗНАЧЕННЯ ВІДОМОСТІ :

Може бути корисним дати кілька простих визначень для номенклатури Spark:

Вузол : сервер

Worker Node : сервер, який є частиною кластеру і доступний для запуску Spark завдань

Головний вузол : сервер, який координує вузли Worker.

Виконавець : Це якась віртуальна машина всередині вузла. В одному Вузлі може бути декілька виконавців.

Вузол драйвера : Вузол, який ініціює іскровий сеанс. Як правило, це буде сервер, на якому розміщений sparklyr.

Драйвер (Виконавець) : Вузол драйвера також з’явиться у списку Виконавця.


1

Іскровий динамічний розподіл дає гнучкість і динамічно розподіляє ресурси. У цій кількості мін та максимум виконавців можуть бути задані. Також може бути вказана кількість виконавців, які повинні бути запущені при запуску заявки.

Читайте нижче про те ж:

http://spark.apache.org/docs/latest/configuration.html#dynamic-allocation


1

У перших двох конфігураціях, які я думаю, є невелике питання. Поняття ниток і сердечників виглядають наступним чином. Концепція нарізки полягає в тому, що якщо ядра ідеальні, тоді використовувати це ядро ​​для обробки даних. Таким чином, пам'ять не використовується повністю в перших двох випадках. Якщо ви хочете визначити цей приклад, виберіть машини, які мають більше 10 ядер на кожній машині. Потім зробіть розмітку лавки.

Але не дайте більше 5 ядер на одного виконавця, на вході / виводу буде шийка пляшки.

Тому найкращими машинами для маркування цього стенду можуть бути вузли даних, які мають 10 ядер.

Специфікація вузла даних: CPU: Core i7-4790 (кількість ядер: 10, кількість потоків: 20) ОЗУ: 32 ГБ (8 ГБ х 4) HDD: 8 ТБ (2 ТБ х 4)


0

Я думаю, що однією з головних причин є місцевість. Ваш розмір вхідного файлу - 165G, пов'язані з ним файли, безумовно, розподілені по декількох DataNodes, більше виконавців може уникнути мережевої копії.

Спробуйте встановити кількість виконавців рівним числом блоків, я думаю, може бути швидше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.