GNU parallel este un instrument de linie de comandă pentru executarea lucrărilor în paralel.

parallel este minunat și aparține în cutia de instrumente a fiecărui programator. Dar am găsit documentele cam copleșitor la început. Din fericire, poți începe să fii util cu parallel cu doar câteva comenzi de bază.

De ce este parallel atat de util?

Să comparăm executarea secvențială și paralelă a aceleiași sarcini intensive.

Imaginați-vă că aveți un dosar de fișiere audio .wav pe care să le convertiți în .flac:

Cum sa va supraincarcati fluxurile de lucru bash cu paralel
fișiere .wav

Acestea sunt fișiere destul de mari, fiecare este cel puțin un gigabyte.

Vom folosi un alt instrument excelent pentru linia de comandă, ffmpeg, pentru a converti fișierele. Iată ce trebuie să rulăm pentru fiecare fișier.

ad-banner
ffmpeg -i audio1.wav audio1.flac

Să scriem un script pentru a le converti pe fiecare în mod secvențial:

# convert.sh
ffmpeg -i audio1.wav audio1.flac
ffmpeg -i audio2.wav audio2.flac
ffmpeg -i audio3.wav audio3.flac
ffmpeg -i audio4.wav audio4.flac
ffmpeg -i audio5.wav audio5.flac

Putem cronometra executarea unei lucrări anticipând time la apelarea scriptului de la terminal. time va imprima timpul real scurs în timpul execuției.

time ./convert.sh

Scenariul nostru se termină peste puțin peste un minut.

1611957605 68 Cum sa va supraincarcati fluxurile de lucru bash cu paralel
momentul executării secvențiale

Nu-i rău. Dar acum să-l rulăm în paralel!

Nu trebuie să schimbăm nimic despre scenariul nostru. Cu -a steag, ne putem introduce direct scriptul parallel. parallel va rula fiecare linie ca o comandă separată.

parallel -a ./convert.sh

Folosind parallel, conversia noastră a durat puțin peste jumătate din timp. Grozav!

1611957605 196 Cum sa va supraincarcati fluxurile de lucru bash cu paralel
momentul executării paralele

Cu doar cinci fișiere, această diferență nu este atât de mare. Dar cu liste mai mari și sarcini mai lungi, putem economisi mult timp parallel.

am întâlnit parallel în timp ce lucrați cu o sarcină de procesare a datelor care probabil ar fi rulat timp de o oră sau mai mult dacă s-ar face secvențial. Cu parallel, a durat doar câteva minute.

parallel puterea depinde și de computerul dvs. Intel i7 al MacBook Pro-ului meu are doar 4 nuclee. Chiar și această mică sarcină i-a împins pe toți la limita lor:

1611957605 712 Cum sa va supraincarcati fluxurile de lucru bash cu paralel

Computerele mai puternice ar putea avea procesoare cu 8, 16 sau chiar 32 de nuclee, oferind economii masive de timp prin paralelizarea locurilor de muncă.

A fi util cu parallel

Celălalt mare beneficiu al parallel este concizia și simplitatea sa. Să începem cu un script Python urât și să-l convertim într-un apel curat către parallel.

Iată un script Python pentru realizarea conversiei noastre de fișiere audio:

import subprocess
path = Path.home()/'my-data-here'
for audio_file in list(path.glob('*.wav')):
    cmd = ['ffmpeg',
           '-i',
           str(audio_file),
           f'{audio_file.name.split(".")[0]}.flac']
    subprocess.run(cmd, stdout=subprocess.PIPE)

Yikes! Este de fapt o mulțime de cod la care să te gândești doar pentru a converti unele fișiere. (Durează aproximativ 1,2 minute pentru a rula).

Să ne convertim Python în parallel.

Apelarea unui script cu parallel -a

parallel -a your-script-here.sh este drăguțul one-liner pe care l-am folosit mai sus pentru a introduce în scriptul nostru bash.

Acest lucru este minunat, dar necesită să scrieți scriptul bash pe care doriți să îl executați. În exemplul nostru, am scris în continuare fiecare apel individual către ffmpeg în convert.sh.

Interpolare de țevi și șiruri cu parallel

Din fericire, parallel ne oferă o modalitate de a șterge convert.sh în întregime.

Iată tot ce trebuie să alergăm pentru a realiza conversia noastră:

ls *.wav | parallel ffmpeg -i {} {.}.flac

Să descompunem asta.

Primim o listă cu toate fișierele .wav din directorul nostru cu ls *.wav. Atunci facem piping (|) acea listă la parallel.

Paralel oferă câteva modalități utile de a interpola șiruri, astfel încât căile noastre de fișiere sunt introduse corect.

Primul este {}, care parallel înlocuiește automat cu o linie din intrarea noastră.

Al doilea operator este {.}, care va introduce o linie, dar cu orice extensii de fișiere eliminate.

Dacă am extinde comanda rulată de parallel pentru prima noastră linie de intrare, am vedea …

ffmpeg -i audio1.wav audio1.flac

Args cu Parallel

După cum se dovedește, nu avem nevoie nici măcar de a țevi ls pentru a finaliza sarcina noastră. Putem merge mai simplu încă:

parallel ffmpeg -i {} {.}.flac ::: *.wav

Argumente transmise către parallel apar după comandă și sunt separate de :::. În acest caz, argumentul nostru este *.wav, care va furniza lista tuturor fișierelor .wav din directorul nostru. Aceste fișiere devin elementele de intrare pentru rapiditatea noastră parallel loc de munca.

Fapt amuzant: parallel a fost construit de Ole Tange și publicat în 2011. Potrivit acestuia, puteți folosi instrumentul pentru cercetare fără a cita hârtia sursă pentru taxa modestă de 10.000 de euro!

1611957605 824 Cum sa va supraincarcati fluxurile de lucru bash cu paralel

Mulțumesc pentru lectură!