Кого бы вы ни спросили, как правильно создавать программы, одним из ответов будет 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» и создает пустой файл два. Вызов «make all» сначала выполняет инструкции для цели e1, а затем - для e2. Чтобы удалить ранее созданные файлы 1 и 2, просто выполните вызов «make clean».”
Листинг 1
все: e1 e2e1:
прикоснуться к одному
e2:
коснуться двух
чистый:
пм один два
Запуск Make
Обычно вы пишете свой Makefile, а затем просто запускаете команду «make» или «make all» для сборки программного обеспечения и его компонентов. Все мишени построены в последовательном порядке и без распараллеливания. Общее время сборки - это сумма времени, необходимого для создания каждой отдельной цели.
Этот подход хорошо работает для небольших проектов, но занимает довольно много времени для средних и крупных проектов. Этот подход больше не актуален, поскольку большинство текущих процессоров оснащены более чем одним ядром и позволяют выполнять более одного процесса одновременно. Помня об этих идеях, мы рассмотрим, можно ли распараллелить процесс сборки и как это сделать. Цель состоит в том, чтобы просто сократить время сборки.
Внести улучшения
У нас есть несколько вариантов: 1) упростить код, 2) распределить отдельные задачи по разным вычислительным узлам, построить там код и собрать оттуда результат, 3) построить код параллельно на одной машине и 4) объедините варианты 2 и 3.
Вариант 1) не всегда просто. Это требует воли к анализу времени выполнения реализованного алгоритма и знаний о компиляторе, i.е., как компилятор переводит инструкции на языке программирования в инструкции процессора.
Вариант 2) требует доступа к другим вычислительным узлам, например, выделенным вычислительным узлам, неиспользуемым или менее используемым машинам, виртуальным машинам из облачных сервисов, таких как AWS, или арендованной вычислительной мощности из таких сервисов, как LoadTeam [5]. На самом деле такой подход используется для создания программных пакетов. Debian GNU / Linux использует так называемую сеть Autobuilder [17], а RedHat / Fedors использует Koji [18]. Google называет свою систему BuildRabbit, и это прекрасно объясняется в выступлении Айсылу Гринберг [16]. distcc [2] - это так называемый распределенный компилятор C, который позволяет компилировать код на разных узлах параллельно и настраивать собственную систему сборки.
Вариант 3 использует распараллеливание на локальном уровне. Это может быть вариант с наилучшим соотношением затрат и выгод для вас, поскольку он не требует дополнительного оборудования, как в варианте 2. Требование для параллельного запуска Make заключается в добавлении опции -j в вызов (сокращение от -jobs). Это указывает количество заданий, которые выполняются одновременно. В приведенном ниже листинге программа Make запускает 4 задания параллельно:
Листинг 2
$ make --jobs = 4Согласно закону Амдала [23], это сократит время сборки почти на 50%. Имейте в виду, что этот подход хорошо работает, если отдельные цели не зависят друг от друга; например, выход цели 5 не требуется для построения цели 3.
Однако есть один побочный эффект: вывод сообщений о состоянии для каждой цели Make выглядит произвольно, и они больше не могут быть четко назначены цели. Порядок вывода зависит от фактического порядка выполнения задания.
Определить порядок выполнения
Есть ли утверждения, которые помогают Make понять, какие цели зависят друг от друга?? да! Пример Makefile в листинге 3 говорит следующее:
* чтобы создать цель «все», выполните инструкции для e1, e2 и e3
* цель e2 требует, чтобы цель e3 была построена раньше
Это означает, что цели e1 и e3 могут быть построены параллельно, сначала, затем следует e2, как только построение e3 будет завершено, и, наконец,.
Листинг 3
все: e1 e2 e3e1:
прикоснуться к одному
e2: e3
коснуться двух
e3:
коснуться трех
чистый:
пм один два три
Визуализируйте зависимости Make
Умный инструмент make2graph из проекта makefile2graph [19] визуализирует зависимости Make в виде ориентированного ациклического графа. Это помогает понять, как разные цели зависят друг от друга. Make2graph выводит описания графиков в формате точек, которые можно преобразовать в изображение PNG с помощью команды точки из проекта Graphviz [22]. Звонок выглядит следующим образом:
Листинг 4
$ make all -Bnd | make2graph | точка -Tpng -o график.PNGВо-первых, Make вызывается с целью «all», за которой следуют параметры «-B» для безоговорочного построения всех целей, «-n» (сокращение от «-dry-run») для имитации выполнения инструкций для каждой цели и « -d »(« -debug ») для отображения отладочной информации. Вывод передается в make2graph, который передает его вывод в точку, которая генерирует граф файла изображения.png в формате PNG.
График зависимости сборки для листинга 3
Другие компиляторы и системы сборки
Как уже объяснялось выше, Make был разработан более четырех десятилетий назад. С годами параллельное выполнение заданий становится все более важным, и с тех пор выросло количество специально разработанных компиляторов и систем сборки для достижения более высокого уровня распараллеливания. В список инструментов входят:
- Базель [20]
- CMake [4]: сокращает кросс-платформенный Make и создает файлы описания, которые позже используются Make
- distmake [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: параллельное выполнение, https: // www.GNU.org / software / make / manual / html_node / Parallel.html
- [2] distcc: https: // github.com / distcc / distcc
- [3] Джон Грэм-Камминг: подводные камни и преимущества GNU Make Parallelization, https: // www.cmcrossroads.ком / статья / ловушки-и-преимущества-gnu-make-parallelization
- [4] CMake, https: // cmake.org /
- [5] LoadTeam, https: // www.loadteam.com /
- [6] NMake, https: // docs.Майкрософт.com / en-us / cpp / build / reference / nmake-reference?view = msvc-160
- [7] SCons, https: // www.бра.org /
- [8] PyDoit, https: // pydoit.org /
- [9] Waf, https: // gitlab.com / ita1024 / waf /
- [10] Распределенная система сборки (DMS), http: // www.нонгну.org / dms / index.html
- [11] Qmake, https: // doc.qt.io / qt-5 / qmake-руководство.html
- [12] distmake, https: // sourceforge.сеть / проекты / distmake /
- [13] dmake, https: // docs.оракул.com / cd / E19422-01 / 819-3697 / dmake.html
- [14] повторить, https: // повторить.читать.io / en / последний /
- [15] Производитель LSF, http: // sunray2.мит.edu / kits / platform-lsf / 7.0.6/1 / руководства / kit_lsf_guide_source / print / lsf_make.pdf
- [16] Айсылу Гринберг: Создание распределенной системы сборки в Google Scale, Конференция GoTo 2016, https: // gotocon.ru / dl / goto-chicago-2016 / slides / AysyluGreenberg_BuildingADistributedBuildSystemAtGoogleScale.pdf
- [17] Система сборки Debian, сеть Autobuilder, https: // www.дебиан.org / devel / buildd / index.en.html
- [18] koji - система построения и отслеживания числа оборотов в минуту, https: // pagure.io / koji /
- [19] makefile2graph, https: // github.com / lindenb / makefile2graph
- [20] Базель, https: // bazel.строить/
- [21] Учебник по Makefile, https: // makefiletutorial.com /
- [22] Graphviz, http: // www.графвиз.org
- [23] Закон Амдала, Википедия, https: // en.википедия.org / wiki / Amdahl% 27s_law