Stellen Sie sich das folgende Szenario vor. Ich habe zwei Programme A und B. Programm A-Ausgaben für Standardzeilen von Strings, während Programm B Zeilen von Standard aus verarbeitet. Die Verwendung dieser beiden Programme ist selbstverständlich:
foo @ bar: ~ $ A | B
Jetzt ist mir aufgefallen, dass dies nur einen Kern auffrisst; daher frage ich mich:
Teilen sich die Programme A und B die gleichen Rechenressourcen? Wenn ja, gibt es eine Möglichkeit, A und B gleichzeitig auszuführen?
Eine andere Sache, die mir aufgefallen ist, ist, dass A viel schneller läuft als B, daher frage ich mich, ob ich irgendwie mehr B-Programme ausführen und sie die von A ausgegebenen Zeilen parallel verarbeiten lassen könnte.
Das heißt, A würde seine Zeilen ausgeben, und es würde N Instanzen von Programmen B geben, die diese Zeilen lesen (wer sie zuerst liest), sie verarbeiten und sie auf stdout ausgeben.
Meine letzte Frage lautet also:
Gibt es eine Möglichkeit, die Ausgabe zwischen mehreren B-Prozessen an A weiterzuleiten, ohne auf die Rennbedingungen und andere Inkonsistenzen achten zu müssen, die möglicherweise auftreten könnten?
quelle
A | B | C
wie in separaten Prozessen parallel ist, kann es aufgrund der Art der Pipes (B muss auf die Ausgabe von A warten, C muss auf die Ausgabe von B warten) in einigen Fällen immer noch linear sein. Es kommt ganz darauf an, welche Art von Output sie produzieren. Es gibt nicht viele Fälle, in denen das Ausführen von mehrerenB
sehr hilfreich ist. Es ist durchaus möglich, dass das parallele wc-Beispiel langsamer alswc
normal ist, da das Aufteilen mehr Ressourcen beansprucht als das normale Zählen von Zeilen. Mit Vorsicht anwenden.Antworten:
Ein Problem dabei
split --filter
ist, dass die Ausgabe verwechselt werden kann, sodass Sie eine halbe Zeile von Prozess 1 gefolgt von einer halben Zeile von Prozess 2 erhalten.GNU Parallel garantiert, dass es keine Verwechslungen geben wird.
Angenommen, Sie möchten Folgendes tun:
Aber dieses B ist furchtbar langsam, und deshalb möchten Sie das parallelisieren. Dann können Sie tun:
GNU Parallel teilt sich standardmäßig auf \ n und eine Blockgröße von 1 MB. Dies kann mit --recend und --block eingestellt werden.
Weitere Informationen zu GNU Parallel finden Sie unter: http://www.gnu.org/s/parallel/
Sie können GNU Parallel in nur 10 Sekunden installieren mit:
Sehen Sie sich das Intro-Video auf http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 an
quelle
--block-size
hängt von der Größe des Arbeitsspeichers ab und davon, wie schnell Sie einen neuen starten könnenB
. In deiner Situation würde ich nutzen--block 100M
und sehen, wie sich das verhält .sh
ist großartig. Das Problem liegt in der Weitergabe an sh: Herunterladen und Ausführen von ausführbarem Code von einer Site . Wohlgemerkt, vielleicht bin ich einfach zu paranoid, da man einwenden könnte, dass ein maßgeschneidertes RPM oder eine maßgeschneiderte DEB im Grunde dasselbe ist, und selbst das Posten des Codes auf einer Seite, die kopiert und eingefügt werden soll, würde dazu führen, dass die Leute dies blind tun wie auch immer.Beim Schreiben laufen
A | B
beide Prozesse bereits parallel. Wenn Sie davon ausgehen, dass sie nur einen Kern verwenden, liegt dies wahrscheinlich an den CPU-Affinitätseinstellungen (möglicherweise gibt es ein Tool, um einen Prozess mit unterschiedlicher Affinität zu erzeugen) oder daran, dass ein Prozess nicht ausreicht, um einen ganzen Kern und das System zu halten. " zieht es vor, "das Computing nicht zu verbreiten".Um mehrere B's mit einem A zu betreiben, benötigen Sie ein Tool wie
split
mit der--filter
Option:Dies kann jedoch die Zeilenreihenfolge in der Ausgabe durcheinander bringen, da die B-Jobs nicht alle mit der gleichen Geschwindigkeit ausgeführt werden. Wenn dies ein Problem ist, müssen Sie möglicherweise die B i-te Ausgabe in eine Zwischendatei umleiten und diese am Ende mit zusammenfügen
cat
. Dies kann wiederum einen beträchtlichen Speicherplatz erfordern.Es gibt andere Optionen (z. B. können Sie jede Instanz von B auf eine einzelne zeilengepufferte Ausgabe beschränken, warten, bis eine ganze "Runde" von Bs beendet ist, das Äquivalent einer Reduction- to
split
- Map ausführen undcat
die temporäre Ausgabe zusammen ausführen ). mit unterschiedlichen Wirkungsgraden. Die soeben beschriebene Option 'round' wartet darauf, dass die langsamste Instanz von B beendet wird. Sie hängt daher stark von der verfügbaren Pufferung für B ab.[m]buffer
kann helfen oder auch nicht, je nachdem, welche Operationen durchgeführt werden.Beispiele
Generieren Sie die ersten 1000 Zahlen und zählen Sie die Zeilen parallel:
Wenn wir die Zeilen "markieren" würden, würden wir sehen, dass jede erste Zeile an Prozess 1 gesendet wird, jede fünfte Zeile an Prozess 5 und so weiter. Darüber hinaus ist
split
der erste Prozess in der Zeit, die zum Starten des zweiten Prozesses benötigt wird, bereits ein guter Weg, um sein Kontingent zu erhöhen:Bei der Ausführung auf einem 2-Kern - Maschine
seq
,split
und diewc
Prozesse teilen sich die Kerne; Bei näherer Betrachtung belässt das System die ersten beiden Prozesse auf CPU0 und teilt CPU1 unter den Arbeitsprozessen auf:Beachten Sie, dass besonders
split
viel CPU verbraucht wird. Dies wird proportional zu den Bedürfnissen von A abnehmen. dh wenn A ein schwererer Prozess ist alsseq
,split
verringert sich der relative Overhead von . Aber wenn A ein sehr leichter Prozess ist und B ziemlich schnell ist (so dass Sie nicht mehr als 2-3 Bs benötigen, um mit A mitzuhalten), lohnt es sich möglicherweise nicht, mitsplit
(oder allgemein mit Pipes) zu parallelisieren .quelle
split
--filter
Option fehlt? Auf meinem Ubuntu 12.04-LTS ("wheezy / sid") ist es da und meine Beispiele funktionieren. Könnten Sie eine anderesplit
als die in GNU coreutils installiert haben ?