Ein besserer Unix-Fund bei Parallelverarbeitung?

43

Das Unix- find(1)Dienstprogramm ist sehr nützlich, damit ich eine Aktion für viele Dateien ausführen kann, die bestimmten Spezifikationen entsprechen, z

find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;

Mit den oben genannten Schritten wird möglicherweise ein Skript oder Tool für jede XML-Datei in einem bestimmten Verzeichnis ausgeführt.

Angenommen, mein Skript / Programm benötigt viel CPU-Zeit und ich habe 8 Prozessoren. Es wäre schön, bis zu 8 Dateien gleichzeitig zu verarbeiten.

GNU make erlaubt die parallele Verarbeitung von Jobs mit dem -jFlag, findscheint jedoch keine solche Funktionalität zu haben. Gibt es eine alternative generische Job-Scheduling-Methode, um dies zu erreichen?

PP.
quelle

Antworten:

65

xargsmit der -POption (Anzahl der Prozesse). Angenommen, ich wollte alle Protokolldateien in einem Verzeichnis auf einem 4-CPU-Computer komprimieren:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2

Sie können auch -n <number>die maximale Anzahl von Arbeitseinheiten pro Prozess angeben . Angenommen, ich hatte 2500 Dateien und sagte:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2

Dies würde 4 bzip2Prozesse starten , von denen jeder 500 Dateien enthält, und dann, wenn der erste einen anderen beendet hat, für die letzten 500 Dateien.

Ich bin mir nicht sicher, warum die vorherige Antwort " xargs und" verwendet make . Sie haben dort zwei parallele Engines.

Gaius
quelle
7
Seien Sie bei find / xargs vorsichtig: find verwendet standardmäßig Zeilenumbrüche als Ausgabetrennzeichen, xargs verwendet standardmäßig Leerzeichen als Eingabetrennzeichen. Verwenden Sie -0 für beide, um sicher zu sein, oder wechseln Sie zu GNU parallel, wobei Zeilenumbrüche standardmäßig als Eingabe-Begrenzer verwendet werden (passend zur Ausgabe von find).
Ephemient
1
Wow, großartig! Ich habe gerade geprüft, und es ist wahr, Xargs hat eine -POption!
PP.
Hüten Sie sich vor der Verwendung der xargs -P- es hat einen nie behobenen Fehler, die Ausgabe zu verstümmeln (im Gegensatz zu parallel), wenn 2 Threads genau zum gleichen Zeitpunkt eine Ausgabe erzeugen ...
Vlad
34

GNU parallel kann auch helfen.

find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}

Beachten Sie, dass ohne das -j8Argument parallelstandardmäßig die Anzahl der Kerne auf Ihrem Computer verwendet wird :-)

vergänglich
quelle
6

Keine Notwendigkeit zu "reparieren" find- machen Sie Gebrauch von sich makeselbst, um die Parallelität zu handhaben.

Lassen Sie Ihren Prozess eine Protokolldatei oder eine andere Ausgabedatei erstellen und verwenden Sie dann ein Makefile wie das folgende:

.SUFFIXES:  .xml .out

.xml.out:
        java -jar ProcessFile.jar $< 1> $@

und so aufgerufen:

find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8

Besser noch, wenn Sie sicherstellen, dass die Ausgabedatei erst nach erfolgreichem Abschluss des Java-Prozesses erstellt wird, können Sie die makeAbhängigkeitsbehandlung nutzen, um sicherzustellen, dass beim nächsten Mal nur nicht verarbeitete Dateien verarbeitet werden.

Alnitak
quelle
1
Hoffentlich gibt es in diesen Dateinamen keine Leerzeichen oder andere "interessante" Zeichen. Make geht damit nicht sehr elegant um.
Ephemient
Exzellente Idee! Ich hätte nie gedacht, Makefiles wie dieses zu verwenden.
oscfri
3

Suchen hat eine parallele Option, die Sie direkt mit dem Symbol "+" verwenden können. Keine Xargs erforderlich. Wenn Sie es mit grep kombinieren, kann es schnell nach Streichhölzern suchen. Wenn ich zum Beispiel nach allen Dateien in meinem Quellverzeichnis suche, die die Zeichenfolge 'foo' enthalten, kann ich sie aufrufen
find sources -type f -exec grep -H foo {} +

Mark Evans
quelle
12
Beim Lesen des Suchhandbuchs können Sie feststellen, dass die -exec command +Syntax es nicht parallel ausführt, sondern viele Dateien "gruppiert" und den Befehl mit mehreren Dateien als Argumente gleichzeitig ausführt. Es kommt vor, dass grep seine Ziele parallel durchsehen kann.
Gyscos