Hai mai la strana sensazione che il tuo computer non sia veloce come dovrebbe? Mi sentivo così, e poi ho trovato GNU Parallel.
GNU Parallel è un'utilità di shell per l'esecuzione di lavori in parallelo. Può analizzare più input, eseguendo così lo script o il comando su set di dati contemporaneamente. Puoi usare tutti finalmente la tua CPU!
Se hai mai usato xargs
, sai già come usare Parallel. In caso contrario, questo articolo ti insegna, insieme a molti altri casi d'uso.
Installazione di GNU Parallel
GNU Parallel potrebbe non essere preinstallato sul tuo computer Linux o BSD. Installalo dal tuo repository o dalla raccolta di porte. Ad esempio, su Fedora:
$ sudo dnf install parallel
O su NetBSD:
# pkg_add parallel
Se tutto il resto fallisce, fai riferimento alla home page del progetto.
Da seriale a parallelo
Come suggerisce il nome, il punto di forza di Parallel è che gestisce i lavori in parallelo anziché, come molti di noi fanno ancora, in sequenza.
Quando esegui un comando su molti oggetti, stai intrinsecamente creando una coda. Un certo numero di oggetti può essere elaborato dal comando e tutti gli altri oggetti restano in attesa e aspettano il proprio turno. È inefficiente. Con dati sufficienti, ci sarà sempre una coda, ma invece di avere una sola coda, perché non avere tante piccole code?
Immagina di avere una cartella piena di immagini che desideri convertire da JPEG a PNG. Ci sono molti modi per farlo. C'è il modo manuale per aprire ogni immagine in GIMP ed esportarla nel nuovo formato. Di solito è il peggior modo possibile. Non è solo dispendioso in termini di tempo, ma anche di manodopera.
Una bella variazione su questo tema è la soluzione basata su shell:
$ convert 001.jpeg 001.png
$ convert 002.jpeg 002.png
$ convert 003.jpeg 003.png
... and so on ...
È un ottimo trucco quando lo impari per la prima volta e all'inizio è un grande miglioramento. Non c'è bisogno di una GUI e di un clic costante. Ma è ancora laborioso.
Meglio ancora:
$ for i in *jpeg; do convert $i $i.png ; done
Questo, almeno, mette in moto i lavori e ti libera per fare cose più produttive. Il problema è che è ancora un processo seriale. Un'immagine viene convertita, quindi la successiva nella coda passa alla conversione e così via fino a quando la coda non viene svuotata.
Con Parallelo:
$ find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png
Questa è una combinazione di due comandi:il find
comando, che raccoglie gli oggetti su cui vuoi operare, e il comando parallel
comando, che ordina gli oggetti e si assicura che tutto venga elaborato come richiesto.
find . -name "*jpeg"
trova tutti i file nella directory corrente che terminano conjpeg
.parallel
invoca GNU Parallel.-I%
crea un segnaposto, chiamato%
, per sostituire qualsiasi cosafind
passa a Parallel. Lo usi perché altrimenti dovresti scrivere manualmente un nuovo comando per ogni risultato difind
, ed è esattamente quello che stai cercando di evitare.--max-args 1
limita la velocità con cui Parallel richiede un nuovo oggetto dalla coda. Poiché il comando Parallel è in esecuzione richiede solo un file, limiti la velocità a 1. Stavi eseguendo un comando più complesso che richiedeva due file (comecat 001.txt 002.txt > new.txt
), limiteresti la tariffa a 2.convert % %.png
è il comando che vuoi eseguire in Parallelo.
Il risultato di questo comando è che find
raccoglie tutti i file rilevanti e li consegna a parallel
, che avvia un lavoro e richiede immediatamente il successivo in linea. Parallel continua a farlo finché è sicuro avviare nuovi lavori senza paralizzare il computer. Man mano che i vecchi lavori vengono completati, li sostituisce con quelli nuovi, fino a quando tutti i dati a lui forniti non sono stati elaborati. Ciò che richiedeva 10 minuti prima potrebbe richiedere solo 5 o 3 con Parallel.
Ingressi multipli
Il find
command è un eccellente gateway per Parallel fintanto che hai familiarità con find
e xargs
(chiamato collettivamente GNU Find Utilities, o findutils
). Fornisce un'interfaccia flessibile con cui molti utenti Linux sono già a proprio agio ed è abbastanza facile da imparare se sei un nuovo arrivato.
Il find
il comando è abbastanza semplice:fornisci find
con un percorso a una directory in cui si desidera cercare e una parte del nome del file che si desidera cercare. Usa i caratteri jolly per allargare la tua rete; in questo esempio, l'asterisco indica qualsiasi cosa , quindi find
individua tutti i file che terminano con la stringa searchterm
:
$ find /path/to/directory -name "*searchterm"
Per impostazione predefinita, find
restituisce i risultati della sua ricerca un elemento alla volta, con un elemento per riga:
$ find ~/graphics -name "*jpg"
/home/seth/graphics/001.jpg
/home/seth/graphics/cat.jpg
/home/seth/graphics/penguin.jpg
/home/seth/graphics/IMG_0135.jpg
Quando esegui il pipe dei risultati di find
a parallel
, ogni elemento su ogni riga viene trattato come un argomento del comando che è parallel
sta arbitrando. Se, invece, devi elaborare più di un argomento in un comando, puoi suddividere il modo in cui i dati nella coda vengono consegnati a parallel
.
Ecco un esempio semplice e irrealistico, che in seguito trasformerò in qualcosa di più utile. Puoi seguire questo esempio, purché tu abbia installato GNU Parallel.
Supponiamo di avere quattro file. Elencali, uno per riga, per vedere esattamente quello che hai:
$ echo ada > ada ; echo lovelace > lovelace
$ echo richard > richard ; echo stallman > stallman
$ ls -1
ada
lovelace
richard
stallman
Vuoi combinare due file in un terzo che contiene il contenuto di entrambi i file. Ciò richiede che Parallel abbia accesso a due file, quindi -I%
la variabile non funzionerà in questo caso.
Il comportamento predefinito di Parallel è praticamente invisibile:
$ ls -1 | parallel echo
ada
lovelace
richard
stallman
Ora dì a Parallel che vuoi ottenere due oggetti per lavoro:
$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman
Ora le linee sono state combinate. Nello specifico, due risultati da ls -1
vengono passati a Parallel tutti in una volta. Questo è il numero giusto di argomenti per questo compito, ma in realtà sono un argomento in questo momento:"ada lovelace" e "richard stallman". Quello che vuoi in realtà sono due argomenti distinti per lavoro.
Fortunatamente, quel tecnicismo viene analizzato da Parallel stesso. Se imposti --max-args
a 2
, ottieni due variabili, {1}
e {2}
, che rappresentano la prima e la seconda parte dell'argomento:
$ ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person
In questo comando, la variabile {1}
è ada o richard (a seconda del lavoro che guardi) e {2}
può essere lovelace
o stallman
. Il contenuto dei file viene reindirizzato con un simbolo di reindirizzamento tra virgolette (le virgolette prendono il simbolo di reindirizzamento da Bash in modo che Parallel possa usarlo) e le inseriscono in nuovi file chiamati ada_lovelace.person
e richard_stallman.person
.
$ ls -1
ada
ada_lovelace.person
lovelace
richard
richard_stallman.person
stallman
$ cat ada_*person
ada lovelace
$ cat ri*person
richard stallman
Se trascorri tutto il giorno ad analizzare file di registro di dimensioni di centinaia di megabyte, potresti vedere come l'analisi parallela del testo potrebbe esserti utile; in caso contrario, questo è principalmente un esercizio dimostrativo.
Tuttavia, questo tipo di elaborazione è prezioso per qualcosa di più della semplice analisi del testo. Ecco un esempio di vita reale dal mondo del cinema. Considera una directory di file video e file audio che devono essere uniti.
$ ls -1
12_LS_establishing-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...and so on...
Utilizzando gli stessi principi, è possibile creare un semplice comando in modo che i file vengano combinati in parallelo :
$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv
Brudo. Forza.
Tutta questa fantasiosa analisi di input e output non è per tutti i gusti. Se preferisci un approccio più diretto, puoi lanciare comandi a Parallel e andartene.
Innanzitutto, crea un file di testo con un comando su ogni riga:
$ cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar
Quindi consegna il file a Parallel:
$ parallel --jobs 6 < jobs2run
E ora tutti i lavori nel tuo file vengono eseguiti in parallelo. Se esistono più lavori di quelli consentiti, viene formata una coda e mantenuta da Parallel finché tutti i lavori non sono stati eseguiti.
Molto, molto di più
GNU Parallel è uno strumento potente e flessibile, con molti più casi d'uso di quelli che possono rientrare in questo articolo. La sua pagina man fornisce esempi di cose davvero interessanti che puoi fare con esso, dall'esecuzione remota su SSH all'incorporazione di funzioni Bash nei tuoi comandi Parallel. C'è anche un'ampia serie di dimostrazioni su YouTube, quindi puoi imparare direttamente dal team di GNU Parallel. Il responsabile della manutenzione di GNU Parallel ha anche appena rilasciato la guida ufficiale del comando, disponibile su Lulu.com.
GNU Parallel ha il potere di cambiare il modo in cui calcoli e, se non lo fa, cambierà almeno il tempo che il tuo computer trascorre a elaborare. Provalo oggi!