Будь-кого, кого ви запитаєте, як правильно створювати програмне забезпечення, запропонує Make як одну з відповідей. У системах GNU / Linux GNU Make [1] - це версія оригінального Make з відкритим вихідним кодом, випущена більше 40 років тому - в 1976 році. Make працює за допомогою Makefile - структурованого звичайного текстового файлу з такою назвою, який найкраще можна описати як інструкцію з побудови процесу побудови програмного забезпечення. Makefile містить ряд міток (так звані цілі) та конкретні інструкції, необхідні для виконання кожної цілі.
Простіше кажучи, Make - це інструмент побудови. Це слідує рецепту завдань із Makefile. Це дозволяє повторювати кроки в автоматизованому режимі, а не вводити їх у терміналі (і, можливо, робити помилки під час набору тексту).
У лістингу 1 наведено приклад Makefile з двома цілями "e1" і "e2", а також двома спеціальними цілями "all" і "clean."Запуск" make e1 "виконує інструкції для цілі" e1 "і створює порожній файл. Запуск “make e2” робить те саме для цілі “e2” і створює два порожні файли. Виклик “зробити все” спочатку виконує інструкції для цілі e1 та e2 наступної. Щоб видалити раніше створені файли один і два, просто виконайте виклик “make clean."
Лістинг 1
всі: e1 e2e1:
торкніться одного
e2:
торкніться двох
чистий:
rm один два
Запуск Make
Поширеним випадком є те, що ви пишете свій файл Make, а потім просто запускаєте команду “make” або “make all” для створення програмного забезпечення та його компонентів. Всі цілі будуються в послідовному порядку і без будь-якого розпаралелювання. Загальний час побудови - це сума часу, необхідного для побудови кожної окремої цілі.
Цей підхід добре працює для невеликих проектів, але займає досить багато часу для середніх та великих проектів. Цей підхід вже не сучасний, оскільки більшість поточних процесорів оснащені більш ніж одним ядром і дозволяють виконувати більше одного процесу одночасно. З огляду на ці ідеї, ми розглядаємо, чи можна і як паралельно розпочати процес побудови. Метою є просто скоротити час збірки.
Зробити вдосконалення
У нас є кілька варіантів - 1) спростити код, 2) розподілити окремі завдання на різні обчислювальні вузли, побудувати там код і зібрати звідти результат, 3) побудувати код паралельно на одній машині та 4) поєднати варіанти 2 і 3.
Варіант 1) не завжди простий. Це вимагає волі проаналізувати час реалізації реалізованого алгоритму та знання про компілятор, тобто.e., як компілятор переводить інструкції мовою програмування в інструкції процесора.
Варіант 2) вимагає доступу до інших обчислювальних вузлів, наприклад, виділених обчислювальних вузлів, невикористаних або менш використовуваних машин, віртуальних машин із хмарних служб, таких як AWS, або орендованих обчислювальних потужностей у таких служб, як LoadTeam [5]. Насправді цей підхід використовується для побудови програмних пакетів. Debian GNU / Linux використовує так звану мережу Autobuilder [17], а RedHat / Fedors - Кодзі [18]. Google називає свою систему BuildRabbit, і це чудово пояснено в доповіді Айсилу Грінберга [16]. distcc [2] - це так званий розподілений компілятор C, який дозволяє паралельно компілювати код на різних вузлах та налаштовувати власну систему збірки.
Варіант 3 використовує розпаралелювання на місцевому рівні. Це може бути варіант з найкращим для вас співвідношенням витрат і вигод, оскільки для нього не потрібно додаткове обладнання, як у варіанті 2. Вимога запускати паралельно Make - це додавання опції -j у виклик (скорочення від -jobs). Це визначає кількість завдань, які виконуються одночасно. У наведеному нижче списку пропонується зробити паралельно 4 роботи:
Лістинг 2
$ make --jobs = 4Відповідно до закону Амдала [23], це скоротить час збірки майже на 50%. Майте на увазі, що такий підхід добре працює, якщо окремі цілі не залежать одна від одної; наприклад, вихід цілі 5 не потрібен для побудови цілі 3.
Однак є один побічний ефект: вихід повідомлень стану для кожного Make target виглядає довільним, і вони більше не можуть бути чітко призначені цілі. Порядок виведення залежить від фактичного порядку виконання завдання.
Визначте Зробити наказ про виконання
Чи існують твердження, які допомагають зрозуміти, які цілі залежать одна від одної? Так! У прикладі Makefile в лістингу 3 сказано наступне:
* щоб побудувати цільове значення "всі", виконайте інструкції для e1, e2 та e3
* ціль e2 вимагає побудови цілі e3 раніше
Це означає, що цілі e1 та e3 можна будувати паралельно, спочатку, потім e2 слідує, як тільки побудова e3 завершується, нарешті.
Лістинг 3
всі: e1 e2 e3e1:
торкніться одного
e2: e3
торкніться двох
e3:
торкніться трьох
чистий:
rm один два три
Візуалізуйте Виконання залежностей
Розумний інструмент make2graph із проекту makefile2graph [19] візуалізує створення залежностей як спрямований ациклічний графік. Це допомагає зрозуміти, як різні цілі залежать одна від одної. Make2graph виводить описи графіків у крапковому форматі, який ви можете перетворити у зображення PNG, використовуючи команду dot із проекту Graphviz [22]. Виклик такий:
Лістинг 4
$ make all -Bnd | make2graph | dot -Tpng -o графік.PNGПо-перше, викликається Make із ціллю “все”, за якою йдуть опції “-B” для безумовної побудови всіх цілей, “-n” (скорочення від “-dry-run”), щоб зробити вигляд, що виконує інструкції для цілі, і “ -d ”(“ -debug ”) для відображення інформації про налагодження. Вихідні дані направляються в трубу make2graph, яка передає вихідні дані у крапку, яка генерує графік файлу зображення.PNG у форматі PNG.
Графік залежності від побудови для списку 3
Більше компіляторів та систем побудови
Як вже пояснювалося вище, Make було розроблено більше чотирьох десятиліть тому. З роками паралельне виконання робочих місць набувало дедалі більшого значення, і з тих пір зросла кількість спеціально розроблених компіляторів та систем побудови для досягнення більш високого рівня розпаралелювання. Список інструментів включає такі:
- Базель [20]
- CMake [4]: скорочує крос-платформну Make і створює файли опису, які пізніше використовуються Make
- розподілити [12]
- Система розподілених марок (DMS) [10] (схоже, мертва)
- dmake [13]
- Марка LSF [15]
- Apache Maven
- Мезон
- Збірка ніндзя
- NMake [6]: Зробити для Microsoft Visual Studio
- PyDoit [8]
- Qmake [11]
- повторити [14]
- SCons [7]
- Вафля [9]
Більшість із них розроблені з урахуванням розпаралелювання та пропонують кращий результат щодо часу збірки, ніж Make.
Висновок
Як ви вже переконалися, варто подумати про паралельні збірки, оскільки це значно скорочує час збірки до певного рівня. Однак досягти цього непросто, і це має певні підводні камені [3]. Перш ніж переходити до паралельних збірок, рекомендується проаналізувати як ваш код, так і шлях його збірки.
Посилання та посилання
- [1] GNU Make Manual: Parallel Execution, https: // www.гну.org / software / make / manual / html_node / Parallel.html
- [2] distcc: https: // github.com / distcc / distcc
- [3] Джон Грем-Каммінг: Підводні камені та переваги GNU роблять паралелізацію, https: // www.cmcrossroads.com / article / пастки та переваги-gnu-make-paralelization
- [4] CMake, https: // cmake.орг /
- [5] LoadTeam, https: // www.loadteam.com /
- [6] NMake, https: // docs.Microsoft.com / en-us / cpp / build / reference / nmake-reference?view = msvc-160
- [7] SCons, https: // www.шкури.орг /
- [8] PyDoit, https: // pydoit.орг /
- [9] Waf, https: // gitlab.com / ita1024 / waf /
- [10] Розподілена система виготовлення (DMS), http: // www.нонгну.org / dms / index.html
- [11] Qmake, https: // doc.qt.io / qt-5 / qmake-manual.html
- [12] distmake, https: // sourceforge.net / projects / distmake /
- [13] dmake, https: // docs.оракул.com / cd / E19422-01 / 819-3697 / dmake.html
- [14] переробити, https: // переробити.readthedocs.io / en / останні /
- [15] LSF Make, http: // sunray2.міт.edu / kits / platform-lsf / 7.0.6/1 / guides / kit_lsf_guide_source / print / lsf_make.pdf
- [16] Айсилу Грінберг: Створення розподіленої системи збірки в Google Scale, GoTo Conference 2016, https: // gotocon.com / dl / goto-chicago-2016 / slides / AysyluGreenberg_BuildingADistributedBuildSystemAtGoogleScale.pdf
- [17] Debian Build System, мережа Autobuilder, https: // www.debian.org / devel / buildd / index.en.html
- [18] koji - система побудови та відстеження RPM, https: // pagure.io / koji /
- [19] makefile2graph, https: // github.com / lindenb / makefile2graph
- [20] Базель, https: // базель.побудувати /
- [21] Підручник Makefile, https: // makefiletutorial.com /
- [22] Graphviz, http: // www.graphviz.орг
- [23] Закон Амдала, Вікіпедія, https: // en.вікіпедія.org / wiki / Amdahl% 27s_law