multiproses untuk bash loop

Saya memiliki skrip Bash non-sepele yang kira-kira berbentuk berikut:

# Initialization

<generate_data> | while read line; do

    # Run tests and filters on line

    if [ "$tests_pass" ]; then
        echo "$filtered_line"
    fi

done | sort <sort_option> | <consume_data>

# Finalization

Dibandingkan dengan filter, generator menggunakan sumber daya pemrosesan yang minimal, dan, tentu saja, operasi pengurutan tidak dapat dimulai sampai semua data yang difilter tersedia. Dengan demikian, filter, rangkaian beberapa loop dan kondisional yang ditulis secara asli di Bash, merupakan hambatan pemrosesan, dan satu proses yang menjalankan loop ini menghabiskan seluruh inti.

Tujuan yang berguna adalah untuk mendistribusikan logika ini ke beberapa proses anak yang masing-masing menjalankan loop filter terpisah, dan yang, pada gilirannya, masing-masing menggunakan blok garis dari generator, dan yang masing-masing menghasilkan blok keluaran yang digabungkan ke dalam operasi pengurutan. Fungsionalitas semacam ini tersedia melalui alat seperti GNU Parallel, tetapi penggunaannya memerlukan pemanggilan perintah eksternal agar dapat dijalankan di dalam pipa.

Apakah ada alat atau fitur praktis yang tersedia yang membuat operasi pada skrip dapat didistribusikan ke berbagai proses tanpa mengganggu keseluruhan struktur skrip? Saya tidak mengetahui fitur bawaan Bash, tapi pasti akan berguna.


person epl    schedule 02.12.2019    source sumber
comment
apakah menggunakan xargs saja sudah cukup?   -  person gregory    schedule 02.12.2019
comment
unix.stackexchange.com/questions/103920/ menunjukkan beberapa contoh tentang pemrosesan loop paralel di bash, Semoga dapat bermanfaat bagi anda.   -  person gzh    schedule 02.12.2019
comment
Terima kasih. Saya telah membaca topik itu (103920), tetapi belum menemukan apa pun yang mengarahkan saya pada solusi untuk masalah ini, seperti yang dibangun. Apakah kamu?   -  person epl    schedule 02.12.2019
comment
Apakah Anda yakin itu bukan forking?   -  person that other guy    schedule 02.12.2019
comment
@gregory Itu akan bekerja mirip dengan GNU parallel yang tidak diinginkan OP (walaupun invoking an external command tidak seburuk menjalankan loop di bash). @epl Dimungkinkan untuk mempercepat filter Anda dengan cukup tanpa harus menggunakan perhitungan paralel. Dengan masukan minimal dan keluaran yang diharapkan, seseorang mungkin memberi Anda solusi di sini.   -  person Socowi    schedule 02.12.2019
comment
@Socowi Saya sedang mengembangkan implementasi logika filter yang dioptimalkan. Saya tidak memerlukan bantuan khusus dalam pekerjaan ini. Namun manfaat dari peningkatan yang diterapkan sendiri jauh lebih rendah dibandingkan dengan memanfaatkan lebih banyak perangkat keras secara paralel. Masalah dengan meminta perintah eksternal adalah kurangnya pengelolaan kode sehubungan dengan pemindahan logika filter ke beberapa perintah yang dapat dipanggil secara independen.   -  person epl    schedule 02.12.2019
comment
such an improvement applied by itself is far inferior to that from utilizing more hardware in parallel Aku tidak akan mengandalkannya. Perulangan di bash sangat lambat, bahkan secara paralel sering kali tidak dapat berlari lebih cepat dari bahasa lain atau bahkan alat khusus. Contoh: Untuk menghasilkan angka dari 1 hingga 4'000'000, saya membandingkan pendekatan berikut pada inti empat. Satu putaran bash (16.1 detik); empat bash loop secara paralel (5.2s); satu putaran awk (0,9 detik); dan seq (0,1 detik). Perhatikan bahwa loop di sini hanya menggunakan bawaan. Jika Anda berulang kali memanggil program eksternal, keadaannya akan lebih buruk lagi.   -  person Socowi    schedule 02.12.2019
comment
@Sucowi Tentu saja saya setuju bahwa Bash lambat, tetapi porting berada di luar cakupan sempit topik ini   -  person epl    schedule 02.12.2019
comment
Maaf, saya tidak ingin mendesak Anda untuk menggunakan bahasa yang sama sekali berbeda. Saya hanya ingin mengoptimalkan kode bash Anda untuk filter. Seringkali segala sesuatunya dapat ditulis lebih pendek dan efisien menggunakan alat (bash) yang tepat untuk pekerjaan itu. Anda hanya perlu mengetahui alat apa yang tepat – itulah yang sangat saya sukai tentang pemrograman di bash. Ini seperti teka-teki.   -  person Socowi    schedule 03.12.2019
comment
Bagaimana kalau menggunakan Redis? Anda dapat dengan mudah LPUSH baris/blok ke dalam daftar Redis dan memulai beberapa prosesor yang BRPOP memblokir daftar dan LPUSH menghasilkan daftar lain. Pekerjaan prosesor dapat dijalankan dalam bash, Python, atau C++ di semua mesin di jaringan Anda.   -  person Mark Setchell    schedule 05.12.2019
comment
Contoh Redis... stackoverflow.com/a/22220082/2836621   -  person Mark Setchell    schedule 05.12.2019
comment
Tentu saja ada banyak pendekatan secara umum, tapi sekali lagi, tujuan dari pertanyaan ini sangat sempit berkaitan dengan melestarikan struktur kode yang ada sambil menambahkan pemanfaatan proses paralel. Alasan topik ini adalah untuk memahami keterbatasan dan kemampuan yang ditawarkan oleh bash dan alat terkait, bukan untuk bertukar pikiran tentang strategi umum untuk pemrosesan paralel. Terima kasih.   -  person epl    schedule 07.12.2019
comment
@epl Saya rasa akan lebih mudah menjawab pertanyaan Anda jika Anda mendefinisikan secara tegas apa yang Anda maksud dengan bash dan alat terkait. Tanpa definisi yang tegas, saya pikir Anda akan mendapatkan jawaban, termasuk apa yang menurut penjawab adalah bash dan alat terkait. Misalnya. Menurut saya GNU Parallel adalah alat yang sangat terkait - pada dasarnya hanya masuk akal jika dijalankan dari shell. Namun saya rasa Anda tidak memasukkan GNU Parallel dalam definisi Anda.   -  person Ole Tange    schedule 07.12.2019
comment
Apakah Anda sudah bereksperimen dengan & dan menunggu $!? Saya biasanya menyimpan setiap hasil dalam array, menunggu semua PID selesai, lalu menjalankan proses sortir/final. Saya akan menulis jawaban dengan contoh singkat hari ini jika Anda mau.   -  person Matthieu    schedule 07.12.2019
comment
@OleTange Cukup adil. Saya terutama memikirkan shell bawaan dan panggilan yang dapat dieksekusi yang kemungkinan tersedia di lingkungan *Nix dan yang biasanya digunakan untuk memperluas skrip shell di luar kemampuan asli bawaan. GNU Parallel akan disertakan sebagai alat terkait. Basis data, antrian pesan, dan alat khusus kemungkinan besar tidak akan disertakan. Alat seperti AWK, Perl, dan sed mungkin disertakan, tetapi menulis ulang blok kode dalam bahasa tersebut, meskipun masuk akal, berada di luar maksud pertanyaan, yang lebih merupakan ciri batas dan kemampuan Bash.   -  person epl    schedule 07.12.2019
comment
@epl Masuk akal untuk menyertakan Perl jika Anda juga mengizinkan program Perl: Anda tidak dapat menggunakan Perl tanpa menulis program Perl. GNU Parallel adalah program Perl, dan Anda dapat menjamin program tersebut akan tersedia untuk skrip Anda dengan memasukkannya ke dalam skrip dengan --embed. GNU Parallel diuji secara aktif pada berbagai platform, dan dianggap sebagai bug jika tidak berfungsi pada platform *Nix. Jika | sementara .. selesai | tidak dapat diubah menjadi | paralel --pipa .. | karena dianggap sebagai penulisan ulang sebuah blok, maka menurut saya sulit untuk memberikan jawaban yang tepat selain tidak, itu tidak dapat dilakukan.   -  person Ole Tange    schedule 07.12.2019


Jawaban (2)


Masalah dengan menjalankan perintah eksternal adalah kurangnya pengelolaan kode sehubungan dengan memindahkan logika filter ke beberapa perintah yang dapat dipanggil secara independen.

Jika itu alasannya untuk tidak menggunakan GNU Parallel, sepertinya Anda tidak mengetahui parallel --embed.

--embed dibuat persis karena orang perlu memiliki GNU Parallel di file yang sama dengan kode lainnya.

[output from parallel --embed]

myfilter() {
    while read line; do
      # Run tests and filters on line
      if [ "$tests_pass" ]; then
        echo "$filtered_line"
      fi
    done
}   
export -f myfilter

<generate_data> | parallel --pipe myfilter | sort <sort_option> | <consume_data>

Skrip yang dihasilkan akan berjalan meskipun GNU Parallel tidak diinstal.

person Ole Tange    schedule 05.12.2019
comment
Saya tidak mengetahui --embed, yang tampaknya sangat baru, dan bahkan tidak disertakan dalam distribusi terkini. Tetapi jika tujuan dari opsi ini adalah untuk membuat skrip yang berjalan tanpa ketergantungan, apakah pertanyaan saat ini tidak sepenuhnya tidak berhubungan? - person epl; 07.12.2019

Tujuan yang berguna adalah untuk mendistribusikan logika ini ke beberapa proses anak yang masing-masing menjalankan loop filter terpisah, dan yang, pada gilirannya, masing-masing menggunakan blok garis dari generator, dan yang masing-masing menghasilkan blok keluaran yang digabungkan ke dalam operasi pengurutan. Fungsionalitas semacam ini tersedia melalui alat seperti GNU Parallel, tetapi penggunaannya memerlukan pemanggilan perintah eksternal agar dapat dijalankan di dalam pipa.

Anda jarang akan melihat skrip bash yang tidak menjalankan perintah eksternal. Anda bahkan menggunakan sort di pipa Anda, dan sort merupakan perintah eksternal.

Apakah ada alat yang mudah digunakan ...

Tanpa definisi Anda tentang 'alat yang mudah digunakan', hal itu tidak mungkin dijawab. Saya pribadi menganggap parallel --pipe cmd nyaman, tetapi mungkin itu tidak sesuai dengan definisi Anda.

... atau tersedia fitur yang membuat operasi pada skrip dapat didistribusikan ke berbagai proses tanpa mengganggu keseluruhan struktur skrip? Saya tidak mengetahui fitur bawaan Bash, tapi pasti akan berguna.

Tidak ada Bash bawaan. Ini adalah alasan utama mengapa GNU Parallel memiliki opsi --pipe.

Menggunakan | parallel --pipe myfilter | tampaknya cukup cocok dengan keseluruhan struktur skrip.

person Ole Tange    schedule 07.12.2019
comment
Tentu saja saya tidak keberatan memanggil proses yang dapat dieksekusi seperti sort. Maksud dari komentar yang Anda kutip adalah untuk menarik perhatian pada batasan yang dirasakan bahwa perintah yang akan diteruskan ke Parallel harus berupa executable eksternal, bukan bagian dari skrip saat ini. Apakah Anda menantang persepsi ini? - person epl; 07.12.2019
comment
@epl Karena saya melakukan hal itu di jawaban lain (yaitu meneruskan fungsi yang ditentukan dalam skrip yang sama - bukan yang dapat dieksekusi) saya melakukan menantang persepsi ini. Anda bahkan dapat memberinya alias jika menggunakan env_parallel. - person Ole Tange; 07.12.2019