Mam trzy rodzaje danych, które są w różnych formatach; dla każdego typu danych istnieje skrypt w języku Python, który przekształca go w pojedynczy zunifikowany format.
Ten skrypt w języku Python jest powolny i związany z procesorem (z jednym rdzeniem na komputerze wielordzeniowym), dlatego chcę uruchomić trzy jego wystąpienia - po jednym dla każdego typu danych - i połączyć ich dane wyjściowe, aby je przekazać sort
. Zasadniczo równoważne z tym:
{ ./handle_1.py; ./handle_2.py; ./handle_3.py } | sort -n
Ale z trzema skryptami działającymi równolegle.
Znalazłem to pytanie, gdzie GNU split
było używane do kradzieży okrągłego strumienia stdout między n instancjami skryptu, który obsługuje strumień.
Na podzielonej stronie man:
-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
Zatem r/N
polecenie implikuje „ bez podziału linii ”.
Na tej podstawie wydaje się, że następujące rozwiązanie powinno być wykonalne:
split -n r/3 -u --filter="./choose_script" << EOF
> 1
> 2
> 3
> EOF
Gdzie choose_script
to robi:
#!/bin/bash
{ read x; ./handle_$x.py; }
Niestety widzę przenikanie się linii i wiele nowych linii, których nie powinno tam być.
Na przykład, jeśli zastąpię moje skrypty Pythona kilkoma prostymi skryptami bash, które to robią:
#!/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;
Widzę ten wynik:
1-8394
2-11238
2-22757
1-723
2-6669
3-3690
2-892
2-312511-24152
2-9317
3-5981
Jest to denerwujące - w oparciu o wyciąg ze strony podręcznika, który wkleiłem powyżej, powinien on zachować integralność linii.
Oczywiście działa to, jeśli usunę -u
argument, ale następnie jest buforowany i zabraknie pamięci, ponieważ buforuje dane wyjściowe wszystkich skryptów oprócz jednego.
Gdyby ktoś miał tu jakiś wgląd, byłoby to bardzo mile widziane. Jestem tutaj z głębi.
coproc
wbudowaną wersję bash, chociaż tak naprawdę nie widzę, jak to działa.job1.py > file1 & job2.py > file 2 & job3.py > file3 ; wait ; sort -n file1 file2 file3
?Odpowiedzi:
Spróbuj użyć opcji -u GNU równolegle.
To uruchamia je równolegle, bez buforowania całego procesu.
źródło
X
wIX
informując-I
, że X będzie flaga zastąpienia, czy też stosując-X
flagę, która pozornie ma istotne znaczenie również?parallel -u -X ./handle_{}.sh ::: "1" "2" "3"
i niestety nadal widzę jakieś zakłócenia w wynikach.parallel -u ./handle_{}.sh
, ale wolę to zmienić, ponieważ nawiasy klamrowe mają również znaczenie łączenia poleceń (jak w twoim pytaniu).Próbować:
Jeśli
handle_1.py
pobiera nazwę pliku:Nie chcesz mieszać wyników, więc nie używaj -u.
Jeśli chcesz zachować kolejność (więc wszystkie dane wyjściowe handle_1 są przed uchwytem 2, a zatem możesz uniknąć sortowania):
Jeśli nadal chcesz to posortować, możesz równolegle sortować i wykorzystać
sort -m
:Ustaw $ TMPDIR na katalog, który jest wystarczająco duży, aby pomieścić dane wyjściowe.
źródło
Może czegoś mi brakuje, ale nie możesz po prostu zrobić:
Jeśli chcesz, aby wiersze z każdego procesu nie były przeplatane, łatwiej jest prawdopodobnie upewnić się, że sam proces zapisuje je w pełni i ewentualnie wyłącza buforowanie wyjściowe, ponieważ
write
s do potoku są gwarantowane jako niepodzielne, o ile nie są większe niżPIPE_BUF
. Na przykład, można mieć pewność, że nie buforowanie wyjścia użyć lastdio
i rozmowyfflush
lub cokolwiek odpowiednikiem jestpython
po jednym lub kilka linii zostały napisane.Jeśli nie możesz zmodyfikować skryptów Pythona, możesz:
(z GNU grep) lub:
(Patrz uwagi w komentarzach poniżej, jeśli dane wyjściowe poleceń nie są tekstem)
I robić:
Inną opcją uniknięcia tych 3
lb
procesów jest posiadanie trzech potoków do jednego polecenia, które używaselect
/,poll
aby zobaczyć, skąd pochodzi dane wyjściowe i podaje je dosort
linii, ale wymaga to trochę programowania.źródło
wait
Myślę, że potrzebujesz tam.sort -n
pozostanie, dopóki wszystkie programy, które mają fd otwarte, nie wyjdą.Odpowiedź Flowbok była poprawnym rozwiązaniem. Co dziwne, wyjście GNU
parallel
zostaje zniekształcone, jeśli jest wyprowadzane bezpośrednio do pliku - ale nie, jeśli idzie do tty.Na szczęście
script -c
jest dostępny do naśladowania tty.Nadal są trzy skrypty:
.
.
Następnie jest plik, który zawiera wywołanie połączenia równoległego:
A potem nazywam to tak:
Linie wyjściowe są mieszane linia po linii między wynikami różnych skryptów, ale nie są zniekształcane ani przeplatane w danym wierszu.
Dziwne zachowanie z
parallel
- mogę złożyć raport o błędzie.źródło