Ich habe drei Arten von Daten, die in verschiedenen Formaten vorliegen. Für jeden Datentyp gibt es ein Python-Skript, das ihn in ein einheitliches Format umwandelt.
Dieses Python-Skript ist langsam und CPU-gebunden (an einen einzelnen Kern auf einem Multi-Core-Computer). Daher möchte ich drei Instanzen davon ausführen - eine für jeden Datentyp - und deren Ausgabe kombinieren, um sie weiterzuleiten sort
. Grundsätzlich gleichbedeutend damit:
{ ./handle_1.py; ./handle_2.py; ./handle_3.py } | sort -n
Aber mit den drei Skripten, die parallel laufen.
Ich fand diese Frage, bei der GNU split
verwendet wurde, um einen Standard-Stream zwischen n Instanzen eines Skripts, das den Stream verarbeitet, abzurunden.
Aus der geteilten Manpage:
-n, --number=CHUNKS
generate CHUNKS output files. See below
CHUNKS may be:
N split into N files based on size of input
K/N output Kth of N to stdout
l/N split into N files without splitting lines
l/K/N output Kth of N to stdout without splitting lines
r/N like 'l' but use round robin distributio
Der r/N
Befehl impliziert also " ohne Linien zu teilen ".
Auf dieser Grundlage scheint die folgende Lösung machbar zu sein:
split -n r/3 -u --filter="./choose_script" << EOF
> 1
> 2
> 3
> EOF
Wo choose_script
macht das:
#!/bin/bash
{ read x; ./handle_$x.py; }
Leider sehe ich eine Vermischung von Zeilen - und viele neue Zeilen, die nicht vorhanden sein sollten.
Wenn ich beispielsweise meine Python-Skripte durch einige einfache Bash-Skripte ersetze, die dies tun:
#!/bin/bash
# ./handle_1.sh
while true; echo "1-$RANDOM"; done;
.
#!/bin/bash
# ./handle_2.sh
while true; echo "2-$RANDOM"; done;
.
#!/bin/bash
# ./handle_3.sh
while true; echo "3-$RANDOM"; done;
Ich sehe diese Ausgabe:
1-8394
2-11238
2-22757
1-723
2-6669
3-3690
2-892
2-312511-24152
2-9317
3-5981
Dies ist ärgerlich - basierend auf dem oben eingefügten Manpage-Auszug sollte die Zeilenintegrität erhalten bleiben.
Natürlich funktioniert es, wenn ich das -u
Argument entferne , aber dann ist es gepuffert und mir geht der Speicher aus, da es die Ausgabe aller Skripte bis auf eines puffert.
Wenn jemand hier einen Einblick hat, wäre er sehr dankbar. Ich bin hier überfordert.
coproc
eingebaute Bash ansehen, obwohl ich nicht wirklich sehe, wie es zutrifft.job1.py > file1 & job2.py > file 2 & job3.py > file3 ; wait ; sort -n file1 file2 file3
?Antworten:
Versuchen Sie es mit der Option -u von GNU parallel.
Dadurch werden sie parallel ausgeführt, ohne dass der gesamte Prozess gepuffert wird.
quelle
X
inIX
sagen ,-I
dass X die Flagge für den Ersatz sein wird, oder ist es die Anwendung-X
Flagge, die scheinbar auch eine relevante Bedeutung hat?parallel -u -X ./handle_{}.sh ::: "1" "2" "3"
und leider sehe ich immer noch einiges an Mangeln der Ausgabe.parallel -u ./handle_{}.sh
, aber ich ziehe es vor, es zu ändern, da geschweifte Klammern auch die Bedeutung haben, Befehle zusammenzufügen (wie in Ihrer Frage).Versuchen:
Wenn
handle_1.py
ein Dateiname verwendet wird:Sie möchten nicht, dass die Ausgabe gemischt wird, verwenden Sie also nicht -u.
Wenn Sie die Reihenfolge beibehalten möchten (daher liegt die gesamte Ausgabe von handle_1 vor handle_2 und Sie können möglicherweise das Sortieren vermeiden):
Wenn Sie es dennoch sortieren möchten, können Sie die Sortierung parallelisieren und Folgendes verwenden
sort -m
:Setzen Sie $ TMPDIR auf ein Verzeichnis, das groß genug ist, um die Ausgabe aufzunehmen.
quelle
Vielleicht fehlt mir etwas, aber kannst du nicht einfach Folgendes tun:
Wenn Sie möchten, dass Zeilen von jedem Prozess nicht verschachtelt werden, ist es wahrscheinlich einfacher, sicherzustellen, dass der Prozess sie vollständig schreibt und möglicherweise die Ausgabepufferung deaktiviert, da
write
s in eine Pipe garantiert atomar sind, solange sie nicht größer als sindPIPE_BUF
. Sie können beispielsweise sicherstellen, dass die Ausgabepufferung à lastdio
and call verwendet wirdfflush
oder was auch immer das Äquivalent ist,python
nachdem eine oder mehrere Zeilen geschrieben wurden.Wenn Sie die Python-Skripte nicht ändern können, haben Sie folgende Möglichkeiten:
(mit GNU grep) oder:
(Siehe Hinweise in den Kommentaren unten, wenn es sich bei der Ausgabe der Befehle nicht um Text handelt.)
Und TU:
Eine andere Möglichkeit, diese drei
lb
Prozesse zu vermeiden , besteht darin, drei Pipes zu einem Befehl zu haben, derselect
/ verwendet, umpoll
zu sehen, woher eine Ausgabe kommt, und siesort
zeilenbasiert zuzuführen, aber es erfordert ein wenig Programmierung.quelle
wait
da drin, denke ich.sort -n
so lange bestehen bleiben, bis alle Programme, auf denen ein fd geöffnet ist, beendet wurden.Flowboks Antwort war die richtige Lösung. Seltsamerweise wird die Ausgabe von GNU
parallel
beschädigt, wenn sie direkt in eine Datei ausgegeben wird - aber nicht, wenn sie in eine Datei geht.Glücklicherweise
script -c
ist verfügbar, um eine tty nachzuahmen.Es gibt noch die drei Skripte:
.
.
Dann gibt es eine Datei, die den Aufruf von parallel kapselt:
Und dann nenne ich es so:
Die Zeilen in der Ausgabe werden zeilenweise zwischen den Ausgaben der verschiedenen Skripte gemischt, aber sie werden in einer bestimmten Zeile nicht entstellt oder verschachtelt.
Bizarres Verhalten von
parallel
- Ich kann einen Fehlerbericht einreichen.quelle