2010-06-09 10 views
10

Ich schreibe ein kleines Skript, das den "PNGOUT" util auf ein paar hundert PNG-Dateien aufruft. Ich habe einfach:Bash: Wie man Aufgaben einfach parallelisiert?

find $BASEDIR -iname "*png" -exec pngout {} \; 

Und dann schaute ich auf meinem CPU-Monitor und bemerkte nur eine des Kerns verwendet wurde, was sehr traurig ist.

In der heutigen Zeit von Dual, Quad, Octo und Hexa (?) Kerne Desktop, wie kann ich einfach diese Aufgabe mit Bash parallelisieren? (Es ist nicht das erste Mal, dass ich ein solches Bedürfnis habe, denn eine ganze Reihe dieser Utilities sind Mono-Threading ... Ich hatte bereits den Fall mit MP3-Encodern).

Würde einfach alle pngout im Hintergrund tun? Wie würde mein finden Befehl dann aussehen? (Ich bin mir nicht sicher, wie man das "&" -Zeichen mischt)

Wenn ich drei hunderte Bilder habe, würde das bedeuten, zwischen dreihundert Prozessen zu tauschen, was sowieso nicht gut aussieht !?

Oder sollte ich kopiere meine drei Hunderte von Dateien oder so in „nb dirs“, wo „nb dirs“ die Anzahl der Kerne werden würde, dann gleichzeitig laufen „nb findet“? (was nahe genug wäre)

Aber wie würde ich das tun?

Antwort

18

Beantworten einer eigenen Frage ...Es stellt sich heraus eine relativ unbekannte Funktion des xargs ist Befehl, der verwendet werden kann, das erreichen:

find . -iname "*png" -print0 | xargs -0 --max-procs=4 -n 1 pngout 

Bingo, Instant 4x Speedup auf einer Quad-Cores Maschine :)

+0

Guter Fang. Der Vorteil von Open Source. Jemand hat sich die Zeit genommen, den Spawn- und Überwachungscode in Xargs zu erstellen. Das ist relativ trivial für so etwas wie xargs. Beachten Sie, dass tt wahrscheinlich Ihre CPU-Temperatur für den Zeitraum anheben wird, in dem sie ausgeführt wird. Ich überwache meinen Quadcore und habe selten eine signifikante Last. Es gibt vier BOINC-Aufgaben bis zum Limit, so dass der durchschnittliche Lastwert fast immer etwas über 4 liegt. – BillThor

+4

haha! Ich hatte eine schwache Erinnerung, dass Xargs das können ... aber es machte mehr Spaß, es in bash zu machen, auch wenn es nicht optimal ist. (Anmerkung, benutze -print0 auf find und -0 in xargs, um Probleme mit fiesen Dateinamen zu vermeiden) – Javier

+0

@Javier: es ist sowieso großartig, hier verschiedene Möglichkeiten zu sehen :) Ich habe meine eigene Antwort bearbeitet, um dein * -print0 */* -0 * Vorschlag :) – NoozNooz42

2

Parallellisierung ist selten trivial. In Ihrem Fall können Sie, wenn Sie Dateien in gleich großen Mengen einzeln auswählen können, mehrere Kopien Ihres Suchskripts ausführen. Du willst 300 Bilder im Hintergrund nicht starten. Für Jobs wie diese ist es normalerweise schneller, sie sequenziell auszuführen. Hintergrundinformationen zum Befehl oder zur Stapelverarbeitung sind beide praktikable Optionen.

die Dateien Angenommen durchnumeriert Sie ein Suchmuster wie „[0-4] .png“ für einen Fund und „ [5-9] .png“ auf einem anderen nutzen könnten. Dadurch würden zwei Kerne etwa für die gleiche Zeit laufen.

Landwirtschaft Aufgabe würde eine Dispatcher-Runner-Setup umfassen. Das Bauen, Testen und Ausführen würde eine Weile dauern.

Starten Sie BOINC, um diese Ersatzprozessoren zu verwenden. Wahrscheinlich werden Sie bei der Überwachung der CPU-Frequenz niced-Prozesse ignorieren wollen. Füge Code wie diesen zu rc.local hinzu.

for CPU in /sys/devices/system/cpu/cpu[0-9]*; do 
    echo 1 > ${CPU}/cpufreq/ondemand/ignore_nice_load 
done 
+0

verdammt, antwortete ich meine eigene Frage zur gleichen Zeit hast du deine Antwort gepostet. Interessante Antwort dort. Aber schau, was ich gefunden habe ... Es stellt sich heraus, * xargs * kann verwendet werden, um solche Aufgaben trivialerweise zu parallelisieren :) – NoozNooz42

+0

@ NoozNooz42 'xargs -P 2' wenn unterstützt sollte zwei Kerne schön laden. Es hilft immer wieder die Manpages von Zeit zu Zeit zu überprüfen. Die neueste Version hat viele nützliche Optionen. – BillThor

4

alle Aufgaben im Hintergrund zum Laichen:

find $BASEDIR -iname "*png" | while read f; do 
    pngout "$f" & 
done 

aber das ist natürlich nicht die beste Option ist. ‚N‘ Aufgaben auf einmal zu tun:

i=0 
find $BASEDIR -iname "*png" | while read f; do 
    pngout "$f" & 
    i=$((i+1)) 
    if [[ $i -gt $NTASKS ]]; then 
    wait 
    i=0 
    fi 
done 

es nicht optimal ist, da sie wartet, bis alle konkurrierenden Tasks beendet sind eine andere Gruppe zu beginnen; aber es sollte besser als nichts sein.

+0

+1 zu Ihnen auch ... Jedoch fand ich einen eleganteren (ich denke) Weg, es zu tun, eine relativ unbekannte Eigenschaft des * xargs * Befehls verwendend :) – NoozNooz42

+0

+1 zu Ihnen weiß ich gerade "warte". Ich kann warten, bis meine Aufgabe fertig ist, bevor Sie die Bash verlassen. –

Verwandte Themen