Ktokolwiek zapytasz, jak poprawnie zbudować oprogramowanie, wymyśli Make jako jedną z odpowiedzi. W systemach GNU/Linux, GNU Make [1] jest wersją Open Source oryginalnego Make, wydanego ponad 40 lat temu - w 1976 roku. Make działa z Makefile - ustrukturyzowanym, zwykłym plikiem tekstowym o tej nazwie, który najlepiej można opisać jako podręcznik budowy procesu tworzenia oprogramowania. Makefile zawiera wiele etykiet (zwanych celami) i konkretne instrukcje potrzebne do wykonania, aby zbudować każdy cel.
Mówiąc najprościej, Make to narzędzie do budowania. Jest zgodny z receptą zadań z Makefile. Pozwala powtarzać kroki w sposób zautomatyzowany, zamiast wpisywać je w terminalu (i prawdopodobnie popełniać błędy podczas pisania).
Listing 1 pokazuje przykładowy plik Makefile z dwoma celami „e1” i „e2” oraz dwoma celami specjalnymi „all” i „clean.” Uruchomienie „make e1” powoduje wykonanie instrukcji dla celu „e1” i utworzenie pustego pliku file. Uruchomienie „make e2” robi to samo dla celu „e2” i tworzy pusty plik dwa. Wywołanie „make all” wykonuje najpierw instrukcje dla celu e1 a następnie e2. Aby usunąć wcześniej utworzone pliki jeden i dwa, po prostu wykonaj wywołanie „make clean.”
Lista 1
wszystkie: e1 e2e1:
dotknij jednego
e2:
dotknij dwa
czysty:
rm jeden dwa
Bieganie Make
Częstym przypadkiem jest to, że piszesz plik Makefile, a następnie po prostu uruchamiasz polecenie „make” lub „make all”, aby zbudować oprogramowanie i jego komponenty. Wszystkie cele są budowane w kolejności szeregowej i bez zrównoleglania. Całkowity czas budowy to suma czasu wymagana do zbudowania każdego celu.
Takie podejście sprawdza się w przypadku małych projektów, ale w przypadku średnich i większych projektów trwa dość długo. To podejście nie jest już aktualne, ponieważ większość obecnych procesorów jest wyposażona w więcej niż jeden rdzeń i umożliwia wykonywanie więcej niż jednego procesu jednocześnie. Mając na uwadze te pomysły, przyglądamy się, czy i jak proces kompilacji można zrównoleglać. Celem jest po prostu skrócenie czasu budowy.
Wprowadzaj ulepszenia
Mamy kilka możliwości: 1) uprościć kod, 2) rozdzielić pojedyncze zadania na różne węzły obliczeniowe, zbudować tam kod i zbierać wyniki, 3) zbudować kod równolegle na jednej maszynie, oraz 4) połącz opcje 2 i 3.
Opcja 1) nie zawsze jest łatwa. Wymaga woli analizy czasu wykonania zaimplementowanego algorytmu oraz wiedzy o kompilatorze, i.mi., jak kompilator tłumaczy instrukcje w języku programowania na instrukcje procesora?.
Wariant 2) wymaga dostępu do innych węzłów obliczeniowych, na przykład dedykowanych węzłów obliczeniowych, nieużywanych lub rzadziej używanych maszyn, maszyn wirtualnych z usług w chmurze, takich jak AWS, lub wynajmowanej mocy obliczeniowej z usług takich jak LoadTeam [5]. W rzeczywistości takie podejście jest wykorzystywane do tworzenia pakietów oprogramowania. Debian GNU/Linux używa tak zwanej sieci Autobuilder [17], a RedHat/Fedors używa Koji [18]. Google nazywa swój system BuildRabbit i doskonale to wyjaśnia w rozmowie Aysylu Greenberg [16]. distcc [2] to tak zwany rozproszony kompilator C, który umożliwia równoległe kompilowanie kodu na różnych węzłach i skonfigurowanie własnego systemu kompilacji.
Wariant 3 wykorzystuje równoległość na poziomie lokalnym. Może to być opcja o najlepszym stosunku kosztów do korzyści dla Ciebie, ponieważ nie wymaga dodatkowego sprzętu, jak w opcji 2. Warunkiem równoległego uruchomienia Make jest dodanie opcji -j w wywołaniu (skrót od -jobs). Określa liczbę zadań, które są uruchamiane w tym samym czasie. Poniższa lista prosi o uruchomienie 4 zadań równolegle:
Lista 2
$ make --jobs=4Zgodnie z prawem Amdahla [23] skróci to czas budowy o prawie 50%. Należy pamiętać, że to podejście działa dobrze, jeśli pojedyncze cele nie są od siebie zależne; na przykład wynik celu 5 nie jest wymagany do zbudowania celu 3.
Jest jednak jeden efekt uboczny: wyjście komunikatów o stanie dla każdego celu Make wydaje się arbitralne i nie można ich już wyraźnie przypisać do celu. Kolejność wyjściowa zależy od aktualnej kolejności wykonania zadania.
Zdefiniuj wykonanie zlecenia wykonania
Czy istnieją stwierdzenia, które pomagają Make zrozumieć, które cele są od siebie zależne?? tak! Przykładowy Makefile z Listingu 3 mówi tak:
* aby zbudować cel „wszystkie”, uruchom instrukcje dla e1, e2 i e3
* cel e2 wymaga wcześniejszego zbudowania celu e3
Oznacza to, że cele e1 i e3 mogą być budowane równolegle, najpierw, następnie e2 następuje, gdy tylko budowa e3 zostanie zakończona, w końcu.
Lista 3
wszystkie: e1 e2 e3e1:
dotknij jednego
e2: e3
dotknij dwa
e3:
dotknij trzy
czysty:
rm jeden dwa trzy
Wizualizuj tworzenie zależności
Sprytne narzędzie make2graph z projektu makefile2graph [19] wizualizuje zależności Make jako ukierunkowany graf acykliczny. Pomaga to zrozumieć, w jaki sposób różne cele są od siebie zależne. Make2graph wyświetla opisy wykresów w formacie kropki, które można przekształcić w obraz PNG za pomocą polecenia kropki z projektu Graphviz [22]. Wezwanie wygląda następująco:
Lista 4
$ zrób wszystko -Bnd | make2graph | kropka -Tpng -o wykres.pngPo pierwsze, Make jest wywoływany z celem „all”, a następnie opcjami „-B”, aby bezwarunkowo zbudować wszystkie cele, „-n” (skrót od „-dry-run”), aby udawać uruchamianie instrukcji dla celu, i „ -d” („-debug”), aby wyświetlić informacje debugowania. Dane wyjściowe są przesyłane do programu make2graph, który przesyła dane wyjściowe do kropki, która generuje wykres pliku obrazu.png w formacie PNG.
Wykres zależności kompilacji dla listingu 3
Więcej kompilatorów i systemów budowania
Jak już wyjaśniono powyżej, Make został opracowany ponad cztery dekady temu. Z biegiem lat, równoległe wykonywanie zadań stawało się coraz ważniejsze, a od tego czasu wzrosła liczba specjalnie zaprojektowanych kompilatorów i systemów budujących, aby osiągnąć wyższy poziom zrównoleglania. Lista narzędzi obejmuje:
- Bazylego [20]
- CMake [4]: oznacza skrót międzyplatformowy Make i tworzy pliki opisów używane później przez Make
- film [12]
- Distributed Make System (DMS) [10] (wydaje się być martwy)
- dmake [13]
- Marka LSF [15]
- Apache Maven
- Mezon
- Budowa Ninja
- NMake [6]: Make dla Microsoft Visual Studio
- PyDoit [8]
- Qmake [11]
- przerobić [14]
- SCons [7]
- Waf [9]
Większość z nich została zaprojektowana z myślą o zrównoleglaniu i oferuje lepsze wyniki pod względem czasu budowy niż Make.
Wniosek
Jak widzieliście, warto pomyśleć o równoległych kompilacjach, ponieważ znacznie skraca to czas budowania do pewnego poziomu. Jednak nie jest to łatwe do osiągnięcia i wiąże się z pewnymi pułapkami [3]. Zaleca się przeanalizowanie zarówno kodu, jak i jego ścieżki budowania przed przejściem do równoległych kompilacji.
Linki i referencje
- [1] Podręcznik GNU Make: wykonywanie równoległe, https://www.gnu antylopa.org/software/make/manual/html_node/Parallel.html
- [2] distcc: https://github.com/distcc/distcc
- [3] John Graham-Cumming: Pułapki i zalety zrównoleglania produkcji GNU, https://www.cmrozdroże.com/article/pułapki-i-korzyści-gnu-make-parallelizacja
- [4] CMake, https://cmake.organizacja/
- [5] LoadTeam, https://www.zespół ładowania.pl/
- [6] NMake, https://docs.Microsoft.com/en-us/cpp/build/reference/nmake-reference?widok=msvc-160
- [7] SCons, https://www.szyderstwa.organizacja/
- [8] PyDoit, https://pydoit.organizacja/
- [9] Waf, https://gitlab.com/ita1024/waf/
- [10] Distributed Make System (DMS), http://www.nongnu.org/dms/indeks.html
- [11] Qmake, https://doc.qt.io/qt-5/qmake-podręcznik.html
- [12] produkcja, https://sourceforge.sieć/projekty/produkcja filmów/
- [13] dmake, https://docs.wyrocznia.com/cd/E19422-01/819-3697/dmake.html
- [14] ponawianie, https://ponawianie.przeczytaj dokumentację.io/pl/ostatnie/
- [15] Marka LSF, http://sunray2.mit.edu/zestawy/platforma-lsf/7.0.6/1/przewodniki/kit_lsf_guide_source/print/lsf_make.pdf
- [16] Aysylu Greenberg: Building a Distributed Build System w Google Scale, GoTo Conference 2016, https://gotocon.com/dl/goto-chicago-2016/slides/AysyluGreenberg_BuildingADistributedBuildSystemAtGoogleScale.pdf
- [17] Debian Build System, sieć Autobuilder, https://www.debian.org/devel/buildd/indeks.en.html
- [18] koji - system budowania i śledzenia obrotów, https://pagure.io/koji/
- [19] makefile2graph, https://github.com/lindenb/makefile2graph
- [20] Bazel, https://bazel.budować/
- [21] Samouczek Makefile, https://makefiletutorial.pl/
- [22] Graphviz, http://www.grafiz.organizacja
- [23] Prawo Amdahla, Wikipedia, https://en.Wikipedia.org/wiki/Amdahl%27s_law