Ich möchte viele Dateien verarbeiten und da ich hier eine Reihe von Kernen habe, möchte ich dies parallel tun:
for i in *.myfiles; do do_something $i `derived_params $i` other_params; done
Ich kenne eine Makefile- Lösung, aber meine Befehle benötigen die Argumente aus der Shell-Globbing-Liste. Was ich gefunden habe ist:
> function pwait() {
> while [ $(jobs -p | wc -l) -ge $1 ]; do
> sleep 1
> done
> }
>
Um es zu verwenden, muss man nur setzen und nach den Jobs und einem pwait-Aufruf gibt der Parameter die Anzahl der parallelen Prozesse an:
> for i in *; do
> do_something $i &
> pwait 10
> done
Aber das funktioniert nicht sehr gut, zB habe ich es mit zB einer for-Schleife versucht, die viele Dateien konvertiert, mir aber Fehler gibt und Jobs ungeschehen macht.
Ich kann nicht glauben, dass dies noch nicht getan ist, da die Diskussion über die zsh-Mailingliste mittlerweile so alt ist. Weißt du es besser?
bash
shell
zsh
parallel-processing
Mathematik
quelle
quelle
echo "DONE"
nach der Schleife gesetzt, die ausgeführt wurde, bevor aktive Jobs nicht beendet wurden. => Das hat mich denken lassen, dass Jobs nicht erledigt wurden.Antworten:
Ein Makefile ist eine gute Lösung für Ihr Problem. Sie könnten diese parallele Ausführung in einer Shell programmieren, aber es ist schwierig, wie Sie bemerkt haben. Eine parallele Implementierung von make kümmert sich nicht nur um das Starten von Jobs und das Erkennen ihrer Beendigung, sondern kümmert sich auch um den Lastausgleich, was schwierig ist.
Die Anforderung für das Globbing ist kein Hindernis: Es gibt Implementierungen, die dies unterstützen. GNU make, das über eine Wildcard-Erweiterung wie z. B.
$(wildcard *.c)
Shell-Zugriff verfügt$(shell mycommand)
(weitere Informationen finden Sie im GNU make-Handbuch). Dies ist die Standardeinstellungmake
unter Linux und auf den meisten anderen Systemen verfügbar. Hier ist ein Makefile-Skelett, das Sie möglicherweise an Ihre Bedürfnisse anpassen können:Führen Sie so etwas wie
make -j4
vier Jobs parallel aus odermake -j -l3
halten Sie den Lastdurchschnitt bei 3.quelle
Ich bin mir nicht sicher, wie Ihre abgeleiteten Argumente sind. Mit GNU Parallel http: // www.gnu.org/software/parallel/ können Sie dies tun, um einen Job pro CPU-Kern auszuführen:
Wenn Sie einfach die .extension ändern möchten, kann die {.} Nützlich sein:
Sehen Sie sich das Intro-Video zu GNU Parallel unter http://www.youtube.com/watch?v=OpaiGYxkSuQ an
quelle
Würde es nicht
wait
für Sie funktionieren, den Befehl der Shell zu verwenden ?Ihre Schleife führt einen Job aus, wartet darauf und führt dann den nächsten Job aus. Wenn die oben nicht funktioniert für Sie, dann könnte Ihnen besser funktionieren , wenn Sie bewegen
pwait
nachdone
.quelle
for
Schleifen verwenden, um dies zu begrenzen:for file in *; do for i in {1..10}; do do_something "$i" & done; wait; done
(ungetestet) Das sollte zehn auf einmal tun und warten, bis alle zehn jeder Gruppe fertig sind, bevor Sie mit den nächsten zehn beginnen. Ihre Schleife macht einen nach dem anderen, um den&
Streit zu machen. Weitere Optionen finden Sie in der Frage, mit der JRobert verknüpft hat. Suchen Sie im Stapelüberlauf nach anderen Fragen, die Ihren (und diesen) ähnlich sind.for i in *
. Er würde Argumente mit einer Pipe oder so etwas an die Schleife übergeben müssen. Dann könnten Sie anstelle einer internen Schleife einen inkrementierenden Zähler ausführen und"micro-"wait"-s"
jeden "$ ((i% 32))" -eq '0'wait
mit einer inneren Gegenschleife hat bei mir gut funktioniert. Vielen Dank!Warum hat noch niemand Xargs erwähnt?
Angenommen, Sie haben genau drei Argumente.
Verwenden Sie andernfalls ein Trennzeichen (dafür ist null praktisch):
BEARBEITEN: Für die obigen Schritte sollte jeder Parameter durch ein Nullzeichen getrennt werden, und dann sollte die Anzahl der Parameter mit den xargs -n angegeben werden.
quelle
Ich habe einige der Antworten ausprobiert. Sie machen das Skript etwas komplexer als nötig. Im Idealfall ist die Verwendung
parallel
oderxargs
wäre vorzuziehen, wenn die Operationen innerhalb der for-Schleife kompliziert sind. Es kann jedoch problematisch sein, Dateien mit großen und langen Zeilen zu erstellen, die parallel geliefert werden sollen. Stattdessen könnten wir source wie folgt verwendenSo würde für Ihr Problem die Lösung aussehen
definieren etwas tun als
do_something.sh
}}
mit
xarg
oder ausführengnu parallel
Ich gehe davon aus, dass die funktionale Unabhängigkeit von Iterationen von for impliziert ist.
quelle