Jak uruchamiać równoległe procesy i łączyć wyniki, gdy oba zostaną zakończone


17

Mam skrypt powłoki bash, w którym przepuszczam dane przez około 5 lub 6 różnych programów, a następnie końcowe wyniki do pliku rozdzielanego tabulatorami.

Następnie robię to samo dla osobnego podobnego zestawu danych i wyprowadzam do drugiego pliku.

Następnie oba pliki są wprowadzane do innego programu do analizy porównawczej. np. w celu uproszczenia

Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv
AnalysisProg -i Data1res.csv Data2res.csv

Moje pytanie brzmi: w jaki sposób mogę uruchomić krok 1 i krok 2 jednocześnie (np. Używając &), ale uruchomić krok 3 (AnalysisProg) tylko wtedy, gdy oba są zakończone?

dzięki

ps AnalysisProg nie będzie działać na strumieniu lub fifo.



BTW, czy możesz używać skryptów Perla? Może to dla ciebie bardzo uprościć i możesz bardzo skutecznie wdrożyć to przetwarzanie końcowe i sprawić, by działało ono równolegle bez wysiłku.
Bichoy

Perl ... nie tak bardzo, nie :(
Stephen Henderson

1
Tutaj pokazuję, jak podzielić dane wejściowe na potoki teei przetworzyć je za pomocą dwóch równoległych grepprocesów: unix.stackexchange.com/questions/120333/…
mikeserv

I tutaj pokazuję, jak używać prostych konstrukcji powłoki, aby w pełni proces przebiegał w sposób, który nohupmógłby, ale nadal utrzymywał sposób komunikowania się z procesem: unix.stackexchange.com/questions/121253/…
mikeserv

Odpowiedzi:


27

Zastosowanie wait. Na przykład:

Data1 ... > Data1Res.csv &
Data2 ... > Data2Res.csv &
wait
AnalysisProg

Wola:

  • uruchom potoki Data1 i Data2 jako zadania w tle
  • poczekaj, aż oba zakończą
  • uruchom AnalysisProg.

Zobacz np. To pytanie .


Dzięki, to wygląda dobrze. Spróbuję tego, jeśli powyższe nie działa.
Stephen Henderson

Jeszcze raz, byłem trochę świadomy czekania, ale po przejrzeniu google byłem trochę zmieszany, jak to działa z innym PID itp. Czuję się głupio, teraz widzę, że to po prostu „czekanie”
Stephen Henderson

12

Odpowiedź cxw jest bez wątpienia najlepszym rozwiązaniem, jeśli masz tylko 2 pliki. Jeśli 2 pliki są tylko przykładami, a w rzeczywistości masz 10000 plików, wówczas rozwiązanie „&” nie będzie działać, ponieważ spowoduje to przeciążenie serwera. Do tego potrzebujesz narzędzia takiego jak GNU Parallel:

ls Data* | parallel 'cat {} | this | that |theother | grep |sed | awk |whatever > {}res.csv
AnalysisProg -i *res.csv

Aby dowiedzieć się więcej o GNU Parallel:


Cześć dzięki. W tej chwili mam dwa pliki, ale mam 24 procesory, więc miałem ochotę uruchomić wiele par naraz - choć nie jestem informatykiem, nie jestem pewien, czy warto czytać wąskie gardło na dysku. może to ssę i zobaczę;)
Stephen Henderson

@StephenHenderson w zależności od rozmiaru pliki mogą nadal znajdować się w pamięci podręcznej. Jeśli prędkość jest krytyczna, możesz po prostu użyć tmpfs (a pliki to <<<, to twoja pamięć RAM).
Maciej Piechotka

1
@StephenHenderson Liczbę równoległych zadań można dostosować za pomocą -j, więc spróbuj -j4, a jeśli serwer się nie przeciąża, spróbuj -j6 itd. Ale bądź gotowy na naciśnięcie CTRL-C: GNU Parallel jest doskonałym narzędziem do szybkiego przeciążania serwerów . Zobacz także --load.
Ole Tange

1

Jednym ze sposobów na osiągnięcie tego może być:

AnalysisProg <<PREPROCESS /dev/stdin
$( 
{   process1=$( pipe | line | 1 >&2 & echo $! )
    process2=$( pipe | line | 2 >&2 & echo $! )
    while ps -p $process1 $process2 >/dev/null; do
        sleep 1
    done
} 2>&1
)
#END
PREPROCESS

W ten sposób opieramy się na obu potokach, ale nadal czekamy, aż zakończą działanie, zanim połączą swoje wyjście w stdin, które jest analizowane w niniejszym dokumencie i przekazywane do AnalysisProg. Jeśli możesz waittego użyć, jest to nawet lepsze niż while pspętla, ale w zależności od powłoki waitmożesz sprzeciwić się, jeśli poinstruujesz ją, aby poczekał na proces, który nie jest potomkiem bieżącej powłoki.

Zauważ też, że powyższa metoda zestawi dane wyjściowe - więc oba procesy będą zapisywane jednocześnie. Jeśli zamiast tego chciałbyś, aby były one oddzielone lub dołączone do siebie, możesz zrobić:

AnalysisProg 3<<PREPROCESS /dev/fd/3 /dev/stderr
$(
process1=$(... >&2 ...) 2>/dev/fd/3
...
} 3>/dev/fd/3 2>/dev/stderr
)

Pokazałem już te koncepcje. Prawdopodobnie najlepsze dema są tu i tutaj .


0

Spróbuj tego użyć.

rm -f Data1Res.csv
rm -f Data2Res.csv
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv &
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv &
while true
do
  ps aux | grep -v grep | grep -i -E 'Data1Res.csv|Data2Res.csv' &> /dev/null
  if [ $? -ne 0 ]
  then
    AnalysisProg -i Data1res.csv Data2res.csv
    exit 0
  fi
done

Cóż, to ciężkie. Czy to nie jest jak wynalezienie waitkoła?
John WH Smith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.