Bagaimana menjalankan proses paralel dan menggabungkan output ketika keduanya selesai

14

Saya memiliki skrip bash shell di mana saya menyalurkan beberapa data melalui sekitar 5 atau 6 program yang berbeda kemudian hasil akhir menjadi file yang dibatasi tab.

Saya kemudian melakukan hal yang sama lagi untuk dataset serupa yang terpisah dan output ke file kedua.

Kemudian kedua file tersebut dimasukkan ke dalam program lain untuk analisis komparatif. misalnya untuk mempermudah

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

Pertanyaan saya adalah: bagaimana saya bisa membuat step1 dan step2 berjalan pada saat yang sama (misalnya menggunakan &) tetapi hanya meluncurkan step3 (AnalysisProg) ketika keduanya selesai?

Terima kasih

ps AnalysisProg tidak akan berfungsi pada streaming atau fifo.

Stephen Henderson
sumber
BTW, apakah Anda boleh menggunakan skrip Perl? Ini dapat menyederhanakan masalah ini untuk Anda dan Anda dapat menerapkan pemrosesan pasca ini dengan sangat efisien dan membuatnya berjalan secara paralel dengan mudah.
Bichoy
Perl..tidak banyak, tidak :(
Stephen Henderson
1
Di sini saya mendemonstrasikan bagaimana membagi input antar pipa dengan teedan memprosesnya dengan dua grepproses bersamaan : unix.stackexchange.com/questions/120333/…
mikeserv
Dan di sini saya mendemonstrasikan cara menggunakan konstruksi shell sederhana untuk melatar belakangi sepenuhnya suatu proses dengan cara yang nohupmungkin tetapi masih mempertahankan cara berkomunikasi dengan proses: unix.stackexchange.com/questions/121253/…
mikeserv

Jawaban:

26

Gunakan wait. Sebagai contoh:

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

akan:

  • menjalankan pipa Data1 dan Data2 sebagai pekerjaan latar belakang
  • tunggu mereka berdua selesai
  • jalankan AnalysisProg.

Lihat, misalnya, pertanyaan ini .

cxw
sumber
Terima kasih, itu terlihat bagus. Saya akan coba ini jika cara di atas tidak berhasil.
Stephen Henderson
Terima kasih lagi, saya agak waspada menunggu tetapi setelah sedikit googled bingung dengan cara kerjanya dengan PID yang berbeda dll. Saya merasa bodoh sekarang saya lihat itu hanya "tunggu"
Stephen Henderson
12

Jawaban cxw tidak diragukan lagi solusi yang lebih disukai, jika Anda hanya memiliki 2 file. Jika 2 file hanyalah contoh dan Anda pada kenyataannya memiliki 10.000 file, maka solusi '&' tidak akan berfungsi, karena itu akan membebani server Anda. Untuk itu Anda memerlukan alat seperti GNU Parallel:

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

Untuk mempelajari lebih lanjut tentang GNU Parallel:

Ole Tange
sumber
Hai, terima kasih. Pada saat ini saya memang memiliki dua file, tetapi saya memiliki 24 prosesor jadi saya merasa tergoda untuk mencoba dan menjalankan banyak pasangan sekaligus - meskipun sebagai bukan orang ilmu komputasi saya tidak jelas apakah hambatan pembacaan disk akan membuatnya berharga. mungkin saya akan menghisapnya dan melihatnya;)
Stephen Henderson
@StephenHenderson tergantung pada ukuran file masih dapat di cache. Jika kecepatan sangat penting Anda hanya dapat menggunakan tmpfs (dan file-file tersebut <<< maka RAM Anda).
Maciej Piechotka
1
@StephenHenderson Jumlah pekerjaan paralel dapat disesuaikan dengan -j, jadi coba -j4 dan jika server tidak kelebihan beban, coba -j6 dll. Tetapi bersiaplah untuk menekan CTRL-C: GNU Parallel adalah alat yang sangat baik untuk membebani server dengan cepat . Lihat juga --load.
Ole Tange
1

Salah satu cara untuk melakukan ini bisa terlihat seperti:

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

Dengan cara ini Anda latar belakang kedua pipa tetapi masih menunggu mereka untuk menyelesaikan mengeksekusi sebelum menggabungkan output mereka ke stdin yang dievaluasi dalam dokumen di sini dan diserahkan ke AnalysisProg. Jika Anda dapat menggunakan waitini bahkan lebih baik daripada while psloop, tetapi, tergantung shell, waitbisa keberatan jika Anda memerintahkannya untuk menunggu proses yang bukan anak dari shell saat ini.

Perhatikan juga bahwa metode di atas akan menyusun keluaran - sehingga kedua proses akan ditulis sekaligus. Jika Anda ingin mereka terpisah, atau menambahkan satu sama lain yang mungkin Anda bisa lakukan:

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

Saya telah menunjukkan konsep-konsep ini sebelumnya. Mungkin demo terbaik ada di sini dan di sini .

mikeserv
sumber
0

Coba gunakan ini.

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
Renan Vicente
sumber
Ya itu yang berat. Bukankah ini seperti menciptakan kembali waitroda?
John WH Smith