Kompilowanie kodu równolegle za pomocą Make

Kompilowanie kodu równolegle za pomocą Make

Ktokolwiek zapytasz, jak prawidłowo zbudować oprogramowanie. W systemach GNU/Linux GNU Make [1] to wersja Original Make, która została wydana ponad 40 lat temu - w 1976 roku - w 1976 roku. Make Works z Makefile - ustrukturyzowany plik tekstowy o tej nazwie, który najlepiej opisać jako podręcznik budowy procesu budowania oprogramowania. Makefile zawiera wiele etykiet (zwanych celami) i konkretne instrukcje, które należy wykonać, aby zbudować każdy cel.

Mówiąc po prostu, Make to narzędzie do kompilacji. Postępuje zgodnie z przepisem zadań z makefile. Pozwala powtarzać kroki w zautomatyzowany sposób, zamiast wpisywać je w terminalu (i prawdopodobnie popełniając błędy podczas pisania).

Lista 1 pokazuje przykład Makefile z dwoma celami „E1” i „E2”, a także dwa specjalne cele „Wszystkie” i „Clean.„Uruchamianie„ Make E1 ”wykonuje instrukcje dla celu„ e1 ”i tworzy pusty plik. Uruchomienie „Make E2” robi to samo dla „E2” i tworzy pusty plik dwa. Wezwanie „Make All” wykonuje instrukcje dla Target E1 First, a E2 Następnie. Aby usunąć wcześniej utworzone pliki jeden i dwa, po prostu wykonaj połączenie „Wyczyść się."

Lista 1

Wszystko: e1 e2
E1:
dotknij jednego
E2:
Dotknij dwa
czysty:
Rm jeden dwa

Make

Wspólnym przypadkiem jest to, że piszesz makefile, a następnie po prostu uruchamiasz polecenie „Make” lub „Make All”, aby zbudować oprogramowanie i jego komponenty. Wszystkie cele są zbudowane w kolejności szeregowej i bez równoległości. Całkowity czas budowy to suma czasu wymagana do zbudowania każdego celu.

Takie podejście działa dobrze w przypadku małych projektów, ale trwa dość długo dla średnich i większych projektów. Takie podejście nie jest już aktualne, ponieważ większość obecnych procesorów jest wyposażona w więcej niż jeden rdzeń i umożliwia wykonanie więcej niż jednego procesu na raz. Mając na uwadze te pomysły, patrzymy na to, czy i jak można równoległy proces budowy. Celem jest po prostu skrócenie czasu budowy.

Dokonaj ulepszeń

Istnieje kilka opcji - 1) Uproszczenie kodu, 2) Rozłóż pojedyncze zadania na różne węzły obliczeniowe, zbuduj tam kod i zbieraj stamtąd wynik, 3) Zbuduj kod równolegle na jednym komputerze i 4) Połącz opcje 2 i 3.

Opcja 1) nie zawsze jest łatwa. Wymaga to woli przeanalizowania czasu wykonywania wdrożonego algorytmu i wiedzy na temat kompilatora, i.mi., W jaki sposób kompilator tłumaczy instrukcje w języku programowania na instrukcje procesora.

Opcja 2) Wymaga dostępu do innych węzłów obliczeniowych, na przykład dedykowanych węzłów obliczeniowych, nieużywanych lub mniej używanych maszyn, maszyn wirtualnych z usług chmurowych, takich jak AWS, lub wynajęta energia obliczeniowa z usług takich jak LoadTeam [5]. W rzeczywistości takie podejście służy do budowania pakietów oprogramowania. Debian GNU/Linux używa tak zwanej sieci Autobuilder [17], a Redhat/Fedors używa Koji [18]. Google wywołuje swój system Buildrabbit i jest doskonale wyjaśniony w rozmowie Aysylu Greenberg [16]. Distcc [2] to tak zwany kompilator rozproszony C, który umożliwia kompilowanie kodu na różnych węzłach równolegle i skonfigurowanie własnego systemu kompilacji.

Opcja 3 wykorzystuje równoległość na poziomie lokalnym. Może to być opcja z najlepszym wskaźnikiem kosztów i korzyści dla Ciebie, ponieważ nie wymaga dodatkowego sprzętu, jak w opcji 2. Wymóg uruchamiania równolegle jest dodawanie opcji -j w połączeniu (skrót od -jobs). To określa liczbę zadań, które są wykonywane jednocześnie. Poniższa lista prosi o wykonanie równolegle 4 zadań:

Lista 2

$ make --jobs = 4

Zgodnie z prawem Amdahla [23] skróci to czas budowy o prawie 50%. Należy pamiętać, że takie podejście działa dobrze, jeśli pojedyncze cele nie zależą od siebie; Na przykład wyjście celu 5 nie jest wymagane do budowy celu 3.

Istnieje jednak jeden efekt uboczny: dane wyjściowe komunikatów o stanie dla każdego celu wydaje się arbitralne i nie można ich już wyraźnie przypisać do celu. Zamówienie wyjściowe zależy od rzeczywistej kolejności wykonania zadania.

Zdefiniuj zlecenie wykonania

Czy istnieją stwierdzenia, które pomagają zrozumieć, które cele zależą od siebie? Tak! Przykład Makefile na Listingu 3 mówi to:

* Aby zbudować cel „Wszystkie”, uruchom instrukcje dotyczące E1, E2 i E3

* Target E2 wymaga wcześniejszego budowy E3

Oznacza to, że cele E1 i E3 mogą być zbudowane równolegle, najpierw E2 następuje, gdy tylko budowanie E3 zostanie zakończone, wreszcie.

Lista 3

Wszystkie: E1 E2 E3
E1:
dotknij jednego
E2: E3
Dotknij dwa
E3:
dotknij trzech
czysty:
rm jeden dwa trzy

Wizualizuj zależności

Sprytne narzędzie Make2Grafh z projektu Makefile2Grafh [19] wizualizuje zależności Make jako ukierunkowanego wykresu acyklicznego. Pomaga to zrozumieć, jak różne cele zależą od siebie. Make2Graph Wyświetla opisy wykresów w formacie kropkowym, że możesz przekształcić w obraz PNG za pomocą polecenia kropkowego z projektu GraphViz [22]. Wezwanie jest następujące:

Lista 4

$ Make All -bnd | Make2Grafh | DOT -tpng -o wykres.png

Po pierwsze, Make jest wywoływany z docelowym „wszystkim”, a następnie opcjami „-B”, aby bezwarunkowo zbudować wszystkie cele, „-n” (skrót od „-dry-run”), aby udawać uruchamianie instrukcji na cel i ” -d ”(„ -debug ”) do wyświetlania informacji o debugowaniu. Wyjście jest potraktowane do Make2Grafh, które przenosi swoje wyjście do kropki, które generuje wykres pliku obrazu.PNG w formacie PNG.


Wykres zależności kompilacji do listy 3

Więcej kompilatorów i systemów budujących

Jak już wyjaśniono powyżej, Make został opracowany ponad cztery dekady temu. Z biegiem lat wykonywanie zadań równolegle stało się coraz ważniejsze, a liczba specjalnie zaprojektowanych kompilatorów i systemów kompilacji, aby osiągnąć wyższy poziom równoległości od tego czasu. Lista narzędzi zawiera te:

  • Bazel [20]
  • Cmake [4]: ​​skróć Make i tworzy pliki opisowe, które później używane przez Make
  • Odróżnij [12]
  • Rozproszony system Make (DMS) [10] (wydaje się być martwy)
  • Dmake [13]
  • LSF Make [15]
  • Apache Maven
  • Mezon
  • Ninja Build
  • NMake [6]: Zrób Microsoft Visual Studio
  • Pydoit [8]
  • QMake [11]
  • Redo [14]
  • Sanons [7]
  • WAF [9]

Większość z nich została zaprojektowana z myślą o równoległości i oferuje lepszy wynik dotyczący czasu budowy niż wykonanie.

Wniosek

Jak widziałeś, warto pomyśleć o równoległych kompilacjach, ponieważ znacznie skraca czas budowy do określonego poziomu. Mimo to nie jest łatwy do osiągnięcia i ma pewne pułapki [3]. Zaleca się analizę zarówno kodu, jak i jego ścieżki kompilacji przed wejściem w równoległe kompilacje.

Linki i referencje

  • [1] GNU Make Instrukcja: wykonanie równoległe, https: // www.gnu antylopa.org/oprogramowanie/make/manual/html_node/równolegle.html
  • [2] distcc: https: // github.com/distcc/distcc
  • [3] John Graham-Cumming: pułapki i zalety GNU Make Parallelization, https: // www.Cmcrossroads.com/artykuł/pułapki i-benefits-gnU-make-anglegylizacja
  • [4] cmake, https: // cmake.org/
  • [5] LoadTeam, https: // www.LoadTeam.com/
  • [6] nmake, https: // dokumenty.Microsoft.com/en-us/cpp/build/reference/nmake-reference?Widok = MSVC-160
  • [7] Scons, https: // www.SKANS.org/
  • [8] Pydoit, https: // pydoit.org/
  • [9] WAF, https: // gitlab.com/ITA1024/WAF/
  • [10] rozproszony system Make (DMS), http: // www.Nongnu.org/dms/indeks.html
  • [11] QMake, https: //c.Qt.IO/QT-5/QMake-Manual.html
  • [12] Distmake, https: // źródłoforge.netto/projekty/distmake/
  • [13] Dmake, https: // dokumenty.wyrocznia.com/cd/e19422-01/819-3697/dmake.html
  • [14] Redo, https: // reto.ReadThedocs.IO/en/najnowszy/
  • [15] LSF Make, http: // sunray2.MIT.edu/zestawy/platforma-LSF/7.0.6/1/przewodniki/kit_lsf_guide_source/print/lsf_make.PDF
  • [16] Aysylu Greenberg: Budowanie rozproszonego systemu kompilacji w Google Scale, Goto Conference 2016, https: // gotocon.com/dl/goto-chicago-2016/slajdes/aysyLugreenberg_BuildingAdistributedBuildSystematgooglescale.PDF
  • [17] Debian Build System, Autobuilder Network, https: // www.Debian.org/devel/buildd/indeks.en.html
  • [18] Koji - system budowania i śledzenia RPM, https: // pagure.IO/KOJI/
  • [19] Makefile2Grafh, https: // github.com/lindenb/makefile2Grafh
  • [20] Bazel, https: // bazel.zbudować/
  • [21] Tutorial Makefile, https: // MakeFileTUorial.com/
  • [22] Graphviz, http: // www.GraphViz.org
  • [23] Prawo Amdahla, Wikipedia, https: // en.Wikipedia.org/wiki/amdahl%27S_LAW