Haben Sie jemals das komische Gefühl, dass Ihr Computer nicht so schnell ist, wie er sein sollte? Früher habe ich mich so gefühlt, und dann habe ich GNU Parallel gefunden.
GNU Parallel ist ein Shell-Dienstprogramm zum parallelen Ausführen von Jobs. Es kann mehrere Eingaben analysieren und dadurch Ihr Skript oder Ihren Befehl gleichzeitig mit Datensätzen ausführen. Sie können alle verwenden endlich deine CPU!
Wenn Sie jemals xargs
verwendet haben , wissen Sie bereits, wie man Parallel verwendet. Wenn Sie dies nicht tun, lernen Sie dieser Artikel zusammen mit vielen anderen Anwendungsfällen kennen.
GNU Parallel installieren
GNU Parallel ist möglicherweise nicht auf Ihrem Linux- oder BSD-Computer vorinstalliert. Installieren Sie es aus Ihrem Repository oder Ihrer Ports-Sammlung. Zum Beispiel auf Fedora:
$ sudo dnf parallel installieren
Oder auf NetBSD:
# pkg_add parallel
Wenn alles andere fehlschlägt, besuchen Sie die Projekt-Homepage.
Von seriell zu parallel
Wie der Name schon sagt, liegt die Stärke von Parallel darin, dass Jobs parallel ausgeführt werden und nicht, wie viele von uns es immer noch tun, sequentiell.
Wenn Sie einen Befehl für viele Objekte ausführen, erstellen Sie von Natur aus eine Warteschlange. Einige Objekte können von dem Befehl verarbeitet werden, und alle anderen Objekte stehen einfach herum und warten, bis sie an der Reihe sind. Es ist ineffizient. Wenn genügend Daten vorhanden sind, wird es immer eine Warteschlange geben, aber warum nicht viele kleine Warteschlangen statt nur einer Warteschlange?
Stellen Sie sich vor, Sie haben einen Ordner voller Bilder, die Sie von JPEG in PNG konvertieren möchten. Es gibt viele Möglichkeiten, dies zu tun. Es gibt die manuelle Möglichkeit, jedes Bild in GIMP zu öffnen und es in das neue Format zu exportieren. Das ist meistens der schlechteste Weg. Es ist nicht nur zeitintensiv, sondern auch arbeitsintensiv.
Eine hübsche Variation dieses Themas ist die Shell-basierte Lösung:
$ 001.jpeg 001.png konvertieren
$ 002.jpeg 002.png konvertieren
$ 003.jpeg 003.png konvertieren
... und so weiter ...Es ist ein großartiger Trick, wenn Sie es zum ersten Mal lernen, und zunächst ist es eine enorme Verbesserung. Keine Notwendigkeit für eine GUI und ständiges Klicken. Aber es ist immer noch arbeitsintensiv.
Besser noch:
$ für i in *jpeg; konvertieren Sie $i $i.png; fertigDies bringt zumindest die Arbeit(en) in Gang und gibt Ihnen die Freiheit, produktivere Dinge zu tun. Das Problem ist, es ist immer noch ein serieller Prozess. Ein Bild wird konvertiert, und dann wird das nächste in der Warteschlange konvertiert, und so weiter, bis die Warteschlange geleert wurde.
Mit Parallel:
$ finden . -name "*jpeg" | parallel -I% --max-args 1 % konvertieren %.pngDies ist eine Kombination aus zwei Befehlen:dem
find
Befehl, der die Objekte sammelt, die Sie bearbeiten möchten, und der Befehlparallel
Befehl, der die Objekte sortiert und sicherstellt, dass alles wie gewünscht verarbeitet wird.
find . -name "*jpeg"
findet alle Dateien im aktuellen Verzeichnis, die aufjpeg
enden .parallel
ruft GNU Parallel auf.-I%
erstellt einen Platzhalter namens%
, um für was auch immerfind
steht übergibt an Parallel. Sie verwenden dies, weil Sie andernfalls für jedes Ergebnis vonfind
manuell einen neuen Befehl schreiben müssten , und genau das versuchen Sie zu vermeiden.--max-args 1
begrenzt die Rate, mit der Parallel ein neues Objekt aus der Warteschlange anfordert. Da der parallel ausgeführte Befehl nur eine Datei erfordert, begrenzen Sie die Rate auf 1. Haben Sie einen komplexeren Befehl ausgeführt, für den zwei Dateien erforderlich waren (z. B.cat 001.txt 002.txt > new.txt
), würden Sie die Rate auf 2.
begrenzen convert % %.png
ist der Befehl, den Sie parallel ausführen möchten.
Das Ergebnis dieses Befehls ist find
sammelt alle relevanten Dateien und übergibt sie an parallel
, das einen Job startet und sofort den nächsten in der Reihe anfordert. Parallel tut dies so lange, wie es sicher ist, neue Jobs zu starten, ohne Ihren Computer lahmzulegen. Wenn alte Jobs abgeschlossen sind, ersetzt es sie durch neue, bis alle ihm zur Verfügung gestellten Daten verarbeitet wurden. Was vorher 10 Minuten gedauert hat, dauert mit Parallel vielleicht nur 5 oder 3 Minuten.
Mehrere Eingaben
Der find
Der Befehl ist ein hervorragendes Tor zu Parallel, solange Sie mit find
vertraut sind und xargs
(zusammen GNU Find Utilities oder findutils
genannt ). Es bietet eine flexible Schnittstelle, mit der viele Linux-Anwender bereits vertraut sind, und ist als Neuling ziemlich einfach zu erlernen.
Der find
Der Befehl ist ziemlich einfach:Sie geben find
an mit einem Pfad zu einem Verzeichnis, das Sie durchsuchen möchten, und einem Teil des Dateinamens, nach dem Sie suchen möchten. Verwenden Sie Platzhalterzeichen, um Ihr Netz weiter auszuwerfen; In diesem Beispiel zeigt das Sternchen alles an , also find
findet alle Dateien, die mit der Zeichenfolge searchterm
enden :
$ find /path/to/directory -name "*searchterm"
Standardmäßig find
gibt die Ergebnisse seiner Suche Element für Element zurück, mit einem Element pro Zeile:
$ 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
Wenn Sie die Ergebnisse von find
weiterleiten zu parallel
, wird jedes Element in jeder Zeile als ein Argument für den Befehl behandelt, der parallel
ist ist schlichtend. Wenn Sie hingegen mehr als ein Argument in einem Befehl verarbeiten müssen, können Sie die Übergabe der Daten in der Warteschlange an parallel
aufteilen .
Hier ist ein einfaches, unrealistisches Beispiel, das ich später in etwas Nützlicheres umwandeln werde. Sie können diesem Beispiel folgen, solange Sie GNU Parallel installiert haben.
Angenommen, Sie haben vier Dateien. Listen Sie sie auf, eine pro Zeile, um genau zu sehen, was Sie haben:
$ echo ada> ada; echo lovelace> lovelace
$ echo richard> richard; echo stallman> stallman
$ ls -1
ada
lovelace
richard
stallman
Sie möchten zwei Dateien zu einer dritten kombinieren, die den Inhalt beider Dateien enthält. Dies setzt voraus, dass Parallel Zugriff auf zwei Dateien hat, also -I%
Variable funktioniert in diesem Fall nicht.
Das Standardverhalten von Parallel ist im Grunde unsichtbar:
$ ls -1 | parallel echo
ada
lovelace
richard
stallman
Teilen Sie Parallel jetzt mit, dass Sie zwei Objekte pro Job erhalten möchten:
$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman
Jetzt wurden die Linien kombiniert. Insbesondere zwei ergibt sich aus ls -1
werden auf einmal an Parallel übergeben. Das ist die richtige Anzahl an Argumenten für diese Aufgabe, aber im Moment sind sie praktisch nur ein Argument:„ada lovelace“ und „richard stallman“. Was Sie eigentlich wollen, sind zwei unterschiedliche Argumente pro Job.
Glücklicherweise wird diese Technik von Parallel selbst geparst. Wenn Sie --max-args
festlegen zu 2
erhalten Sie zwei Variablen, {1}
und {2}
, die den ersten und zweiten Teil des Arguments darstellen:
$ ls -1 | parallel --max-args=2 Katze {1} {2} ">" {1}_{2}.person
In diesem Befehl ist die Variable {1}
ist ada oder richard (je nachdem, welchen Job Sie sich ansehen) und {2}
ist entweder lovelace
oder stallman
. Die Inhalte der Dateien werden mit einem Umleitungssymbol in Anführungszeichen umgeleitet (die Anführungszeichen greifen das Umleitungssymbol von Bash, damit Parallel es verwenden kann) und in neue Dateien mit dem Namen ada_lovelace.person
platziert und 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
Wenn Sie den ganzen Tag damit verbringen, Protokolldateien zu parsen, die Hunderte von Megabyte groß sind, werden Sie vielleicht sehen, wie nützlich parallelisiertes Textparsing für Sie sein könnte. ansonsten ist dies meist eine Demonstrationsübung.
Diese Art der Verarbeitung ist jedoch nicht nur für die Textanalyse von unschätzbarem Wert. Hier ist ein reales Beispiel aus der Filmwelt. Stellen Sie sich ein Verzeichnis mit Videodateien und Audiodateien vor, die zusammengefügt werden müssen.
$ ls -1
12_LS_founding-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...und so auf...
Unter Verwendung der gleichen Prinzipien kann ein einfacher Befehl erstellt werden, damit die Dateien parallel kombiniert werden :
$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv
Brutal. Erzwingen.
All dieses ausgefallene Input- und Output-Parsing ist nicht jedermanns Sache. Wenn Sie eine direktere Herangehensweise bevorzugen, können Sie Parallel Befehle geben und weggehen.
Erstellen Sie zunächst eine Textdatei mit einem Befehl in jeder Zeile:
$ 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
Dann übergeben Sie die Datei an Parallel:
$ parallel --jobs 6Und jetzt werden alle Jobs in Ihrer Datei parallel ausgeführt. Wenn mehr Jobs als zulässig vorhanden sind, wird eine Warteschlange gebildet und von Parallel verwaltet, bis alle Jobs ausgeführt wurden.
Viel, viel mehr
GNU Parallel ist ein leistungsstarkes und flexibles Werkzeug mit weitaus mehr Anwendungsfällen, als in diesen Artikel passen. Seine Manpage bietet Beispiele für wirklich coole Dinge, die Sie damit machen können, von der Remote-Ausführung über SSH bis hin zur Integration von Bash-Funktionen in Ihre Parallel-Befehle. Es gibt sogar eine umfangreiche Demonstrationsserie auf YouTube, sodass Sie direkt vom GNU Parallel-Team lernen können. Der Hauptbetreuer von GNU Parallel hat außerdem gerade den offiziellen Leitfaden des Befehls veröffentlicht, der auf Lulu.com erhältlich ist.
GNU Parallel hat die Macht, die Art und Weise, wie Sie rechnen, zu ändern, und wenn dies nicht der Fall ist, wird es zumindest die Zeit ändern, die Ihr Computer mit Rechnen verbringt. Probieren Sie es noch heute aus!