Den du spør hvordan du bygger programvare på riktig måte, vil komme med å lage som et av svarene. På GNU/Linux Systems er GNU Make [1] open source -versjonen av originalen som ble utgitt for mer enn 40 år siden - i 1976. Lag fungerer med en Makefile - en strukturert vanlig tekstfil med det navnet som best kan beskrives som byggehåndboken for programvarebyggingsprosessen. Makefilen inneholder en rekke etiketter (kalt mål) og de spesifikke instruksjonene som må utføres for å bygge hvert mål.
Bare å snakke, lage er et byggeverktøy. Det følger oppskriften på oppgaver fra makefilen. Det lar deg gjenta trinnene på en automatisert måte i stedet for å skrive dem i en terminal (og sannsynligvis gjøre feil mens du skriver).
Oppføring 1 viser et eksempel Makefile med de to målene “E1” og “E2” i tillegg til de to spesielle målene “All” og “Clean.”Kjør“ Make E1 ”utfører instruksjonene for målet“ E1 ”og oppretter den tomme filen en. Å kjøre “Make E2” gjør det samme for målet “E2” og oppretter den tomme filen to. Samtalen til "Make All" utfører instruksjonene for Target E1 først og E2 neste. For å fjerne de tidligere opprettede filene en og to, utfør bare samtalen “Gjør ren.”
Oppføring 1
Alle: E1 E2
E1:
berør en
E2:
berør to
ren:
RM en to
Løping
Den vanlige saken er at du skriver makefilen din og bare kjører kommandoen "Make" eller "Make All" for å bygge programvaren og dens komponenter. Alle målene er innebygd i seriell rekkefølge og uten parallellisering. Den totale byggetiden er summen av tid som kreves for å bygge hvert eneste mål.
Denne tilnærmingen fungerer bra for små prosjekter, men tar ganske lang tid for mellomstore og større prosjekter. Denne tilnærmingen er ikke lenger oppdatert ettersom de fleste av de nåværende CPU-ene er utstyrt med mer enn en kjerne og tillater utførelse av mer enn en prosess om gangen. Med disse ideene i bakhodet ser vi på om og hvordan byggeprosessen kan parallelliseres. Målet er å ganske enkelt redusere byggetiden.
Gjøre forbedringer
Det er noen få alternativer vi har - 1) forenkle koden, 2) distribuere enkeltoppgavene på forskjellige databehandlingsnoder, bygge koden der og samle resultatet derfra, 3) bygge koden parallelt på en enkelt maskin, og 4) Kombiner alternativene 2 og 3.
Alternativ 1) er ikke alltid lett. Det krever viljen til å analysere runtime for den implementerte algoritmen og kunnskapen om kompilatoren, i.e., Hvordan oversetter kompilatoren instruksjonene i programmeringsspråket til prosessorinstruksjoner.
Alternativ 2) krever tilgang til andre databehandlingsnoder, for eksempel dedikerte databehandlingsnoder, ubrukte eller mindre brukte maskiner, virtuelle maskiner fra skytjenester som AWS, eller leid datakraft fra tjenester som LoadTeam [5]. I virkeligheten brukes denne tilnærmingen til å bygge programvarepakker. Debian Gnu/Linux bruker det såkalte Autobuilder Network [17], og Redhat/Fedors bruker Koji [18]. Google kaller systemet BuildRabbit og blir perfekt forklart i samtalen av Aysylu Greenberg [16]. Distcc [2] er en såkalt distribuert C-kompilator som lar deg kompilere kode på forskjellige noder parallelt og sette opp ditt eget byggesystem.
Alternativ 3 bruker parallellisering på lokalt nivå. Dette kan være alternativet med det beste kostnads-fordel-forholdet for deg, da det ikke krever ekstra maskinvare som i alternativ 2. Kravet om å kjøre Make parallelt er å legge til alternativet -J i samtalen (forkortelse for -jobber). Dette spesifiserer antall jobber som kjøres samtidig. Oppføringen nedenfor ber om å gjøre om å kjøre 4 jobber parallelt:
Oppføring 2
$ make -jobs = 4
I følge Amdahls lov [23] vil dette redusere byggetiden med nesten 50%. Husk at denne tilnærmingen fungerer bra hvis de enkeltmålene ikke er avhengig av hverandre; For eksempel er ikke utgangen fra mål 5 påkrevd for å bygge mål 3.
Imidlertid er det en bivirkning: utdataene fra statusmeldingene for hvert MAKE -mål virker vilkårlig, og disse kan ikke lenger tilordnes tydelig til et mål. Utgangsrekkefølgen avhenger av den faktiske ordren på utførelsen av stillingen.
Definer gjøre utførelsesordre
Er det uttalelser som hjelper til med å forstå hvilke mål avhenger av hverandre? Ja! Eksemplet Makefile i Listing 3 sier dette:
* For å bygge mål "alle", kjør instruksjonene for E1, E2 og E3
* Mål E2 krever at mål E3 bygges før
Dette betyr at målene E1 og E3 kan bygges parallelt, først, deretter følger E2 så snart bygningen av E3 er fullført, endelig.
Oppføring 3
Alle: E1 E2 E3
E1:
berør en
E2: E3
berør to
E3:
berør tre
ren:
RM en to tre
Visualiser Make -avhengigheter
Det smarte verktøyet Make2Graph fra Makefile2Graph [19] Prosjekt visualiserer Make -avhengigheter som en rettet acyklisk graf. Dette hjelper til med å forstå hvordan de forskjellige målene er avhengige av hverandre. Make2graph gir ut grafbeskrivelser i prikkformat som du kan forvandle til et PNG -bilde ved å bruke DOT -kommandoen fra GraphViz -prosjektet [22]. Samtalen er som følger:
Oppføring 4
$ gjør alt -bnd | make2graph | Dot -tpng -o graf.png
For det første kalles Make med målet “All” etterfulgt av alternativene “-B” for å ubetinget å bygge alle målene, “-N” (forkortelse for “-dry-run”) for å late som å kjøre instruksjonene per mål, og “ -D ”(“ -Debug ”) for å vise feilsøkingsinformasjon. Utgangen blir rør til Make2Graph som rører utdataene til DOT som genererer bildefilgrafen.PNG i PNG -format.
Byggavhengighetsgrafen for oppføring 3
Flere kompilatorer og byggesystemer
Som allerede forklart ovenfor, ble Make utviklet for mer enn fire tiår siden. Gjennom årene har det blitt mer viktig å utføre jobber parallelt. Listen over verktøy inkluderer disse:
De fleste av dem er designet med tanke på parallellisering og gir et bedre resultat angående byggetid enn å lage.
Konklusjon
Som du har sett, er det verdt å tenke på parallelle bygg, da det reduserer byggetiden opp til et visst nivå betydelig. Likevel er det ikke lett å oppnå og kommer med visse fallgruver [3]. Det anbefales å analysere både koden din og dens byggesti før du går inn i parallelle bygg.
Lenker og referanser