Kompilierer Code parallel mit make make

Kompilierer Code parallel mit make make

Wer auch immer Sie fragen, wie man Software ordnungsgemäß erstellt. Auf GNU/Linux -Systemen ist GNU Make [1] die Open -Source -Version des Original -Maße, das vor mehr als 40 Jahren veröffentlicht wurde - 1976. Machen Sie Arbeiten mit einem Makefile - eine strukturierte Klartextdatei mit diesem Namen, die am besten als Bauhandbuch für den Softwarebauprozess beschrieben werden kann. Das Makefile enthält eine Reihe von Etiketten (als Ziele genannte Ziele) und die spezifischen Anweisungen, die ausgeführt werden mussten, um jedes Ziel zu erstellen.

Einfach sprechen: Make ist ein Build -Tool. Es folgt dem Rezept von Aufgaben aus dem Makefile. Sie können die Schritte automatisch wiederholen, anstatt sie in einem Terminal zu tippen (und wahrscheinlich beim Eingeben Fehler zu machen).

Listing 1 zeigt ein Beispiel Makefile mit den beiden Zielen „E1“ und „E2“ sowie die beiden speziellen Ziele „All“ und „Clean“."Ausführen" "make e1" führt die Anweisungen für das Ziel "E1" aus und erstellt die leere Datei eins. Ausführen von "make e2" macht dasselbe für Ziel "e2" und erstellt die leere Datei zwei. Der Ruf von "Make All" führt die Anweisungen für Target E1 zuerst und E2 als nächstes aus. Um die zuvor erstellten Dateien eins und zwei zu entfernen, führen Sie einfach den Anruf „Machen Sie sauber aus.”

Listing 1

ALL: E1 E2
E1:
Berühren Sie einen
E2:
Berühren Sie zwei
sauber:
rm eins zwei

Laufen machen

Der gemeinsame Fall ist, dass Sie Ihr Makefile schreiben und dann einfach den Befehl "make" oder "make alle" ausführen, um die Software und ihre Komponenten zu erstellen. Alle Ziele sind in serieller Reihenfolge und ohne Parallelisierung eingebaut. Die Gesamtbauzeit ist die Zeitsumme, die für das Erstellen jedes einzelnen Ziels erforderlich ist.

Dieser Ansatz eignet sich gut für kleine Projekte, dauert jedoch ziemlich lange für mittlere und größere Projekte. Dieser Ansatz ist nicht mehr auf dem neuesten. Unter Berücksichtigung dieser Ideen sehen wir uns an, ob und wie der Build -Prozess parallelisiert werden kann. Ziel ist es, einfach die Bauzeit zu verkürzen.

Verbesserungen machen

Es gibt einige Optionen, die wir haben - 1) Vereinfachen Sie den Code, 2) die einzelnen Aufgaben auf verschiedene Computerknoten verteilen, den Code dort erstellen und das Ergebnis von dort aus sammeln, 3) den Code parallel auf einer einzelnen Maschine erstellen und 4) Kombinieren Sie die Optionen 2 und 3.

Option 1) ist nicht immer einfach. Es erfordert den Willen, die Laufzeit des implementierten Algorithmus und des Wissens über den Compiler zu analysieren, i.e., Wie übersetzt der Compiler die Anweisungen in der Programmiersprache in Prozessoranweisungen?.

Option 2) Erfordert Zugriff auf andere Computerknoten, z. B. dedizierte Computerknoten, nicht verwendete oder weniger verwendete Maschinen, virtuelle Maschinen aus Cloud -Diensten wie AWS oder gemietete Rechenleistung von Diensten wie Loadteam [5]. In Wirklichkeit wird dieser Ansatz verwendet, um Softwarepakete zu erstellen. Debian GNU/Linux verwendet das sogenannte Autobuilder-Netzwerk [17], und Redhat/Fedors verwendet Koji [18]. Google ruft seinen System Buildrabbit an und wird im Vortrag von Aysylu Greenberg perfekt erklärt [16]. DistcC [2] ist ein sogenannter verteilter C-Compiler, mit dem Sie parallel auf verschiedenen Knoten kompilieren und Ihr eigenes Build-System einrichten können.

Option 3 verwendet Parallelisierung auf lokaler Ebene. Dies kann die Option mit dem besten Kosten-Nutzen-Verhältnis für Sie sein, da keine zusätzliche Hardware wie in Option 2 erforderlich ist. Die Voraussetzung zum Ausführen parallel ist das Hinzufügen der Option -J im Anruf (kurz für -Jobs). Dies gibt die Anzahl der Jobs an, die gleichzeitig ausgeführt werden. In der folgenden Auflistung wird aufgefordert, 4 Jobs parallel zu machen:

Listing 2

$ make -jobs = 4

Nach Angaben des Amdahls Gesetz [23] wird dies die Bauzeit um fast 50% verkürzen. Denken Sie daran, dass dieser Ansatz gut funktioniert, wenn die einzelnen Ziele nicht voneinander abhängen. Zum Beispiel ist die Ausgabe von Target 5 nicht erforderlich, um Target 3 zu erstellen.

Es gibt jedoch einen Nebeneffekt: Die Ausgabe der Statusnachrichten für jedes Made -Ziel erscheint willkürlich, und diese können nicht mehr eindeutig einem Ziel zugeordnet werden. Die Ausgabereihenfolge hängt von der tatsächlichen Reihenfolge der Arbeitsplatzausführung ab.

Definieren Sie die Ausführungsreihenfolge

Gibt es Aussagen, die dazu beitragen, zu verstehen, welche Ziele voneinander abhängen? Ja! In dem Beispiel Makefile in Listing 3 heißt es: Folgendes:

* Um das Ziel „All“ zu erstellen, führen Sie die Anweisungen für E1, E2 und E3 aus

* Ziel E2 erfordert, dass Target E3 zuvor erstellt werden soll

Dies bedeutet, dass die Ziele E1 und E3 parallel gebaut werden können. Zuerst folgt E2, sobald das Gebäude von E3 abgeschlossen ist, endlich.

Listing 3

ALL: E1 E2 E3
E1:
Berühren Sie einen
E2: E3
Berühren Sie zwei
E3:
drei berühren
sauber:
rm ein zwei drei

Visualisieren Sie die Abhängigkeiten machen

Das clevere Tool make2Graph von Makefile2Graph [19] -Projekt visualisiert die Make -Abhängigkeiten als gerichteten acyclischen Graphen. Dies hilft zu verstehen, wie die verschiedenen Ziele voneinander abhängen. Make2Graph gibt Grafikbeschreibungen im DOT -Format aus, die Sie mit dem Befehl dot aus dem GraphViz -Projekt in ein PNG -Bild verwandeln können [22]. Der Anruf lautet wie folgt:

Listing 4

$ machen alle -bnd | make2graph | dot -tpng -o -Diagramm.png

Erstens wird Make mit dem Ziel "All" aufgerufen, gefolgt von den Optionen "-B", um alle Ziele bedingungslos zu erstellen, "-n" (kurz für "-Dry-Run"), um so zu tun, -D ”(„ -Debug “), um Debug-Informationen anzuzeigen. Die Ausgabe wird so angeleitet, dass 2Graph seine Ausgabe an Punkt verlegt, die das Bilddateigraphen generiert.PNG im PNG -Format.


Das Build -Abhängigkeits -Diagramm für die Auflistung 3

Weitere Compiler und Bausysteme

Wie bereits oben erläutert, wurde Make vor mehr als vier Jahrzehnten entwickelt. Im Laufe der Jahre ist es immer wichtiger geworden, dass die Ausführung von Arbeitsplätzen paralleler geworden ist, und die Anzahl der speziell entwickelten Compiler und Bausysteme, um ein höheres Maß an Parallelisierung zu erreichen, ist seitdem gewachsen. Die Liste der Tools enthält diese:

  • Bazel [20]
  • CMAKE [4]: ​​Abkürzes plattformübergreifende Abkürzung machen und erstellt Beschreibungsdateien, die später von Make verwendet werden
  • Distmake [12]
  • Distributed Make System (DMS) [10] (scheint tot zu sein)
  • Dmake [13]
  • LSF machen [15]
  • Apache Maven
  • Meson
  • Ninja Build
  • NMake [6]: Machen Sie sich für Microsoft Visual Studio
  • Pydoit [8]
  • QMAKE [11]
  • Redo [14]
  • Scons [7]
  • WAF [9]

Die meisten von ihnen wurden unter Berücksichtigung der Parallelisierung entworfen und bieten ein besseres Ergebnis in Bezug auf die Bauzeit als zu machen.

Abschluss

Wie Sie gesehen haben, lohnt es sich, über parallele Erstellungen nachzudenken. Trotzdem ist es nicht einfach zu erreichen und kommt mit bestimmten Fallstricken [3]. Es wird empfohlen, sowohl Ihren Code als auch seinen Build -Pfad zu analysieren, bevor Sie in parallele Builds eintreten.

Links und Referenzen

  • [1] GNU manuell machen: Parallele Ausführung, https: // www.Gnu.org/software/make/manual/html_node/parallel.html
  • [2] DistcC: https: // github.com/distcc/distcc
  • [3] John Graham-Cumming: Die Fallstricke und Vorteile von GNU machen Parallelisierung, https: // www.cmcrossroads.COM/ARTIKEL/PASSFALLE UND NEHFITS-GNU-Make-Parallelisierung
  • [4] CMake, https: // cmake.org/
  • [5] Loadteam, https: // www.Loadteam.com/
  • [6] Nmake, https: // docs.Microsoft.com/en-us/cpp/build/referenz/nmake-referenz?View = MSVC-160
  • [7] Scons, https: // www.Scons.org/
  • [8] Pydoit, https: // pydoit.org/
  • [9] WAF, https: // gitlab.com/ita1024/waf/
  • [10] verteiltes System (DMS), http: // www.Nongnu.org/dms/Index.html
  • [11] QMake, https: // doc.Qt.IO/QT-5/QMAKE-Manual.html
  • [12] Distmake, https: // SourceForge.Netz/Projekte/Distmake/
  • [13] Dmake, https: // docs.Orakel.com/cd/e19422-01/819-3697/dmake.html
  • [14] Redo, https: // Redo.Readthedocs.io/en/letztes/
  • [15] lsf make, http: // sunray2.MIT.EDU/Kits/Plattform-LSF/7.0.6/1/Guides/kit_lsf_guide_source/print/lsf_make.PDF
  • [16] Aysylu Greenberg: Erstellen eines verteilten Build -Systems in Google Scale, GOTO Conference 2016, https: // gotocon.com/dl/goto-chicago-2016/glides/ayylugreenberg_buildingAdvertributedBuildSystematgooglescale.PDF
  • [17] Debian Build System, Autobuilder Network, https: // www.Debian.org/Entwicklung/Buildd/Index.en.html
  • [18] Koji - RPM -Gebäude- und Tracking -System, https: // pagure.io/koji/
  • [19] Makefile2Graph, https: // github.com/lindenb/makefile2Graph
  • [20] Bazel, https: // bazel.bauen/
  • [21] Makefile -Tutorial, https: // makefiletutorial.com/
  • [22] Graphviz, http: // www.Graphviz.Org
  • [23] Amdahls Gesetz, Wikipedia, https: // en.Wikipedia.org/wiki/amdahl%27s_law