GNU Make

Compilarea codului în paralel folosind Make

Compilarea codului în paralel folosind Make

Oricine întrebați cum să creați software corect va veni cu Make ca unul dintre răspunsuri. Pe sistemele GNU / Linux, GNU Make [1] este versiunea Open-Source a originalului Make care a fost lansat acum mai bine de 40 de ani - în 1976. Faceți lucrări cu un Makefile - un fișier text simplu structurat cu acel nume care poate fi cel mai bine descris ca manual de construcție pentru procesul de construire a software-ului. Makefile conține un număr de etichete (numite ținte) și instrucțiunile specifice necesare pentru a fi executate pentru a construi fiecare țintă.

Pur și simplu vorbind, Make este un instrument de construcție. Urmează rețeta sarcinilor din Makefile. Vă permite să repetați pașii într-un mod automat, mai degrabă decât să îi tastați într-un terminal (și probabil să faceți greșeli în timp ce tastați).

Listarea 1 arată un exemplu Makefile cu cele două ținte „e1” și „e2”, precum și cele două ținte speciale „toate” și „curat”.„Rularea„ make e1 ”execută instrucțiunile pentru ținta„ e1 ”și creează fișierul gol. Rularea „make e2” face același lucru pentru ținta „e2” și creează fișierul gol doi. Apelul „make all” execută instrucțiunile pentru ținta e1 mai întâi și e2 următoarea. Pentru a elimina fișierele create anterior unul și doi, pur și simplu executați apelul „make clean.”

Listarea 1

toate: e1 e2
e1:
atinge unul
e2:
atinge doi
curat:
rm unu doi

Alergare Make

Cazul obișnuit este că vă scrieți Makefile și apoi rulați doar comanda „make” sau „make all” pentru a construi software-ul și componentele sale. Toate țintele sunt construite în ordine serială și fără nicio paralelizare. Timpul total de construcție este suma de timp necesară pentru a construi fiecare țintă.

Această abordare funcționează bine pentru proiectele mici, dar durează destul de mult pentru proiectele medii și mai mari. Această abordare nu mai este actualizată, deoarece majoritatea cpus-urilor actuale sunt echipate cu mai mult de un nucleu și permit executarea a mai mult de un proces la un moment dat. Având în vedere aceste idei, ne uităm dacă și cum poate fi paralelizat procesul de construire. Scopul este de a reduce pur și simplu timpul de construire.

Faceți îmbunătățiri

Există câteva opțiuni pe care le avem - 1) simplificăm codul, 2) distribuim sarcinile individuale pe diferite noduri de calcul, construim codul acolo și colectăm rezultatul de acolo, 3) construim codul în paralel pe o singură mașină și 4) combinați opțiunile 2 și 3.

Opțiunea 1) nu este întotdeauna ușoară. Necesită voința de a analiza timpul de rulare al algoritmului implementat și cunoștințele despre compilator, i.e., cum traduce compilatorul instrucțiunile din limbajul de programare în instrucțiuni ale procesorului.

Opțiunea 2) necesită acces la alte noduri de calcul, de exemplu, noduri de calcul dedicate, mașini neutilizate sau mai puțin utilizate, mașini virtuale din servicii cloud precum AWS sau putere de calcul închiriată de la servicii precum LoadTeam [5]. În realitate, această abordare este utilizată pentru a construi pachete software. Debian GNU / Linux folosește așa-numita rețea Autobuilder [17], iar RedHat / Fedors folosește Koji [18]. Google își numește sistemul BuildRabbit și este perfect explicat în discuția de Aysylu Greenberg [16]. distcc [2] este așa-numitul compilator C distribuit care vă permite să compilați coduri pe diferite noduri în paralel și să vă configurați propriul sistem de construire.

Opțiunea 3 utilizează paralelizarea la nivel local. Aceasta poate fi opțiunea cu cel mai bun raport cost-beneficiu pentru dvs., deoarece nu necesită hardware suplimentar ca în opțiunea 2. Cerința de a rula Make în paralel este adăugarea opțiunii -j în apel (scurt pentru -jobs). Aceasta specifică numărul de joburi care se execută în același timp. Listarea de mai jos solicită lui Make să ruleze 4 joburi în paralel:

Listarea 2

$ make --jobs = 4

Conform legii lui Amdahl [23], acest lucru va reduce timpul de construcție cu aproape 50%. Rețineți că această abordare funcționează bine dacă țintele individuale nu depind unele de altele; de exemplu, ieșirea țintei 5 nu este necesară pentru a construi ținta 3.

Cu toate acestea, există un efect secundar: ieșirea mesajelor de stare pentru fiecare Make target pare arbitrară, iar acestea nu mai pot fi atribuite în mod clar unei ținte. Ordinea de ieșire depinde de ordinea reală a execuției lucrării.

Definiți Ordinea de executare

Există declarații care vă ajută să înțelegeți ce ținte depind unele de altele? da! Exemplul Makefile din Listarea 3 spune acest lucru:

* pentru a construi „toate” țintă, rulați instrucțiunile pentru e1, e2 și e3

* ținta e2 necesită construirea țintei e3 înainte

Aceasta înseamnă că obiectivele e1 și e3 pot fi construite în paralel, mai întâi, apoi e2 urmează imediat ce construirea e3 este finalizată, în cele din urmă.

Listarea 3

toate: e1 e2 e3
e1:
atinge unul
e2: e3
atinge doi
e3:
atingeți trei
curat:
rm unu doi trei

Vizualizați creați dependențe

Instrumentul inteligent make2graph din proiectul makefile2graph [19] vizualizează dependențele Make ca un grafic aciclic direcționat. Acest lucru ajută la înțelegerea modului în care diferite ținte depind unele de altele. Make2graph generează descrieri ale graficelor în format punct pe care le puteți transforma într-o imagine PNG folosind comanda punct din proiectul Graphviz [22]. Apelul este următorul:

Listarea 4

$ make all -Bnd | make2graph | punct -Tpng -o grafic.png

În primul rând, Make este apelat cu ținta „all” urmată de opțiunile „-B” pentru a construi necondiționat toate țintele, „-n” (prescurtarea „-dry-run”) pentru a pretinde că rulează instrucțiunile per țintă și „ -d ”(„ -debug ”) pentru a afișa informații de depanare. Ieșirea este conectată la make2graph, care țeavă ieșirea la punct care generează graficul fișierului imagine.png în format PNG.


Graficul dependenței de compilare pentru listarea 3

Mai multe compilatoare și sisteme de construcție

După cum sa explicat mai sus, Make a fost dezvoltat acum mai bine de patru decenii. De-a lungul anilor, executarea de locuri de muncă în paralel a devenit din ce în ce mai importantă, iar numărul de compilatoare special concepute și sisteme de construire pentru a atinge un nivel mai ridicat de paralelizare a crescut de atunci. Lista instrumentelor include următoarele:

Cele mai multe dintre ele au fost proiectate având în vedere paralelizarea și oferă un rezultat mai bun în ceea ce privește timpul de construcție decât Make.

Concluzie

După cum ați văzut, merită să vă gândiți la versiunile paralele, deoarece reduce semnificativ timpul de construcție până la un anumit nivel. Totuși, nu este ușor de realizat și vine cu anumite capcane [3]. Este recomandat să vă analizați atât codul, cât și calea de construire a acestuia înainte de a intra în versiuni paralele.

Linkuri și referințe

Open Source Ports of Commercial Game Engines
Free, open source and cross-platform game engine recreations can be used to play old as well as some of the fairly recent game titles. This article wi...
Cele mai bune jocuri de linie de comandă pentru Linux
Linia de comandă nu este doar cel mai mare aliat al tău când folosești Linux - poate fi și sursa de divertisment, deoarece poți să o folosești pentru ...
Best Gamepad Mapping Apps for Linux
If you like to play games on Linux with a gamepad instead of a typical keyboard and mouse input system, there are some useful apps for you. Many PC ga...