Angenommen, ich möchte alle Übereinstimmungen in einer komprimierten Textdatei finden:
$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern
pv --rate
wird hier zur Messung des Rohrdurchsatzes verwendet. Auf meinem Computer sind es ungefähr 420 MBit / s (nach der Dekomprimierung).
Jetzt versuche ich paralleles grep mit GNU parallel zu machen.
$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern
Jetzt sinkt der Durchsatz auf ~ 260 MBit / s. Und was noch interessanter parallel
ist, ist, dass viel CPU verbraucht wird. Mehr als grep
Prozesse (aber weniger als gzcat
).
EDIT 1 : Ich habe verschiedene Blockgrößen ( --block
) sowie verschiedene Werte für -N
/ -L
options ausprobiert . An dieser Stelle hilft mir nichts.
Was mache ich falsch?
quelle
--pipe
es ineffizient ist? Ich meine, ist es ein grundlegendes Problem oder eher ein spezifisches Implementierungsproblem?--pipe
jedem einzelnen Byte den einzelnen Prozess durchlaufen, der für jedes Byte ein wenig verarbeitet werden muss. Die--pipepart
meisten Bytes werden vom zentralen Prozess nie gesehen: Sie werden von gespawnten Jobs verarbeitet. Da es nur wenige Zeilen gibt, die den Engpass darstellen,--pipe
würde ich einen C / C ++ - Codierer begrüßen, der den Teil neu schreibt, der dann für Leute ausgeführt wird, die C-Compiler im Pfad haben.grep ist sehr effektiv - es macht keinen Sinn, es parallel auszuführen. In Ihrem Befehl benötigt nur die Dekomprimierung mehr CPU, dies kann jedoch nicht parallelisiert werden.
Das Teilen von Eingaben durch Parallele benötigt mehr CPU als das Teilen von übereinstimmenden Zeilen durch Grep.
Situationsänderung, wenn Sie anstelle von grep etwas verwenden möchten, das für jede Zeile viel mehr CPU benötigt - dann hätte Parallel mehr Sinn.
Wenn Sie diesen Vorgang beschleunigen möchten - schauen Sie, wo Engpässe liegen - wahrscheinlich ist es Dekomprimierung (hilft dann bei der Verwendung eines anderen Dekomprimierungswerkzeugs oder einer besseren CPU) oder - Lesen von der Festplatte (dann Hilfe bei der Verwendung eines anderen Dekomprimierungswerkzeugs oder eines besseren Festplattensystems).
Nach meiner Erfahrung - manchmal ist es besser, lzma (zum Beispiel -2) zum Komprimieren / Dekomprimieren von Dateien zu verwenden - hat es eine höhere Komprimierung als gzip, sodass viel weniger Daten von der Festplatte gelesen werden müssen und die Geschwindigkeit vergleichbar ist.
quelle
Die Dekompression ist hier der Engpass. Wenn die Dekomprimierung nicht intern parallelisiert wird, erreichen Sie sie nicht selbst. Wenn Sie mehr als einen solchen Job haben, starten Sie sie natürlich parallel, aber Ihre Pipeline allein ist schwer zu parallelisieren. Das Aufteilen eines Streams in parallele Streams lohnt sich fast nie und kann beim Synchronisieren und Zusammenführen sehr schmerzhaft sein. Manchmal muss man einfach akzeptieren, dass mehrere Kerne nicht bei jeder einzelnen Aufgabe helfen, die Sie ausführen.
Im Allgemeinen sollte die Parallelisierung in der Shell hauptsächlich auf der Ebene unabhängiger Prozesse erfolgen.
quelle
parallel
. Ich stimme zu, dass dies sicherlich im ersten Fall (ohne Parallele) der Fall ist, aber im zweiten Fall (mit Parallelität) liegt der Engpass auf der parallelen Seite. Dies folgt aus der Beobachtung, dass der Durchsatz signifikant abfällt, gemessen durchpv
. Wenn der Engpass dekomprimiert wird, ändert der Durchsatz nichts, was Sie der Pipeline hinzufügen. Ich denke, es ist eine sehr intuitive Definition des Durchsatzes - die Sache, die den Durchsatz am meisten einschränkt.parallel
es in seine Pipe schreiben kann. In diesem Fallgrep
warten die meisten Prozesse einfach darauf, mehr zu erhalten, währendparallel
sie rund um die Uhr arbeiten, um die Blöcke in mehrere Pipes zu multiplexen (dies sind zusätzliche E / A-Operationen und können sogar die Dekomprimierung blockieren, wenn der Puffer voll ist). Haben Sie auch versucht, mit dem--block
Parameter zu spielen ? Der Standardwert ist1M
so lange, bis ein Grep1M
Daten erhält . Der Rest ist mit ziemlicher Sicherheit bereits erledigt. Daher kommen wir auf die Tatsache zurück, dass es keinen Sinn macht, dies zu parallelisieren.-N
/-L
options. Es scheint, als ob die Standardoptionen dem lokalen Optimum sehr nahe kommen, das ich erlebt habe :)pv
(mittime
) zu steuern . Auf diese Weise können Sie sehen, ob es sichpv
selbst verlangsamt. Wenn dies derparallel
Fall ist, ist das Kopieren von Daten in Pipes definitiv ein zusätzlicher Aufwand. Und auf jeden Fall bin ich mir ziemlich sicher, dassgrep
dies in diesem Fall fast in Echtzeit geschieht, insbesondere wenn das Muster eine einfache Zeichenfolge ohne viel Backtracking ist. Zusätzlichparallel
werden diegrep
Ausgänge verschachtelt und durcheinander gebracht .pv
selbst das Problem nicht verursacht, danke für den Rat.