Saya punya tugas yang memproses daftar file di stdin. Waktu memulai program sangat besar, dan jumlah waktu yang dibutuhkan setiap file sangat bervariasi. Saya ingin menelurkan sejumlah besar proses ini, kemudian mengirim pekerjaan ke mana saja yang tidak sibuk. Ada beberapa alat commandline berbeda yang hampir melakukan apa yang saya inginkan, saya mempersempitnya menjadi dua opsi yang hampir berfungsi:
find . -type f | split -n r/24 -u --filter="myjob"
find . -type f | parallel --pipe -u -l 1 myjob
Masalahnya adalah split
apakah melakukan round-robin murni, sehingga salah satu proses tertinggal dan tetap di belakang, menunda penyelesaian seluruh operasi; sementara parallel
ingin menelurkan satu proses per N baris atau byte input dan akhirnya saya menghabiskan terlalu banyak waktu untuk overhead startup.
Apakah ada sesuatu seperti ini yang akan menggunakan kembali proses dan memberi makan garis ke proses mana saja yang telah membuka blokir stdins?
sumber
split
perintah itu? Nama tersebut bertentangan dengan utilitas pemrosesan teks standar .myjob
siap untuk menerima lebih banyak input. Tidak ada cara untuk mengetahui bahwa suatu program siap untuk memproses lebih banyak input, yang dapat Anda ketahui adalah bahwa beberapa buffer di suatu tempat (buffer pipa, buffer stdio) siap menerima input lebih banyak. Bisakah Anda mengatur program Anda untuk mengirim beberapa jenis permintaan (mis. Tampilkan konfirmasi) ketika sudah siap?read
panggilan akan melakukan trik. Itu upaya pemrograman yang cukup besar.-l 1
diparallel
args? IIRC, yang memberitahukan secara paralel untuk memproses satu baris input per pekerjaan (yaitu satu nama file per garpu myjob, sehingga banyak overhead startup).Jawaban:
Itu tidak terlihat mungkin dalam kasus umum seperti itu. Ini menyiratkan Anda memiliki buffer untuk setiap proses dan Anda dapat menonton buffer dari luar untuk memutuskan di mana menempatkan entri berikutnya (penjadwalan) ... Tentu saja Anda dapat menulis sesuatu (atau menggunakan sistem batch seperti slurm)
Tetapi tergantung pada apa prosesnya, Anda mungkin dapat melakukan pra-proses input. Sebagai contoh jika Anda ingin mengunduh file, memperbarui entri dari DB, atau serupa, tetapi 50% dari mereka akan berakhir dilewati (dan karenanya Anda memiliki perbedaan pemrosesan yang besar tergantung pada input) lalu, cukup siapkan pra-prosesor yang memverifikasi entri mana yang akan memakan waktu lama (file ada, data telah diubah, dll), jadi apa pun yang datang dari pihak lain dijamin akan memakan waktu yang cukup sama. Bahkan jika heuristik tidak sempurna Anda mungkin berakhir dengan peningkatan yang cukup besar. Anda dapat membuang yang lain ke file dan memprosesnya dengan cara yang sama.
Tapi itu tergantung pada kasus penggunaan Anda.
sumber
Tidak, tidak ada solusi umum. Operator Anda perlu tahu kapan setiap program siap membaca baris lain, dan tidak ada standar yang saya ketahui yang memungkinkan untuk itu. Yang bisa Anda lakukan adalah memasang STDOUT dan menunggu sesuatu untuk mengkonsumsinya; benar-benar tidak ada cara yang baik bagi produsen untuk memastikan apakah konsumen berikutnya siap atau tidak.
sumber
Saya kira tidak. Di majalah favorit saya adalah sebuah artikel tentang pemrograman bash yang melakukan apa yang Anda inginkan. Saya bersedia percaya bahwa jika ada alat untuk melakukan itu mereka akan menyebutkannya. Jadi, Anda menginginkan sesuatu seperti:
Jelas Anda dapat mengubah permintaan untuk skrip yang aktif sesuai keinginan Anda. Majalah yang saya sebutkan awalnya melakukan hal-hal seperti memasang pipa dan benar-benar memulai thread pekerja. Lihat
mkfifo
itu, tetapi rute itu jauh lebih rumit karena proses pekerja perlu memberi sinyal pada proses master bahwa mereka siap menerima lebih banyak data. Jadi Anda memerlukan satu fifo untuk setiap proses pekerja untuk mengirimkan data dan satu fifo untuk proses master untuk menerima barang dari pekerja.DISCLAIMER Saya menulis naskah itu dari atas kepala saya. Mungkin ada beberapa masalah sintaksis.
sumber
find . -type f | while read i
daripadafor i in $(find . -type f)
.Untuk GNU Parallel Anda dapat mengatur ukuran blok menggunakan --block. Namun, itu mengharuskan Anda memiliki cukup memori untuk menyimpan 1 blok dalam memori untuk setiap proses yang berjalan.
Saya mengerti ini bukan apa yang Anda cari, tetapi mungkin ini merupakan solusi yang dapat diterima untuk saat ini.
Jika tugas Anda rata-rata membutuhkan waktu yang sama, maka Anda mungkin dapat menggunakan mbuffer:
sumber
Coba ini:
mkfifo
untuk setiap proses.Kemudian bertahan
tail -f | myjob
di setiap fifo.Misalnya menyiapkan pekerja (proses pekerjaanku)
Tergantung pada aplikasi Anda (pekerjaan saya) Anda mungkin dapat menggunakan pekerjaan -s untuk menemukan pekerjaan yang dihentikan. Kalau tidak, daftarkan proses yang diurutkan berdasarkan CPU dan pilih sumber daya yang paling sedikit dikonsumsi. Tentu memiliki laporan pekerjaan itu sendiri, misalnya dengan menetapkan bendera di sistem file ketika ingin lebih banyak pekerjaan.
Dengan asumsi pekerjaan berhenti ketika menunggu input, gunakan
jobs -sl
untuk mengetahui pid dari pekerjaan yang berhenti dan menetapkannya bekerja, misalnyaSaya menguji ini dengan
Ini harus saya akui hanya diciptakan jadi ymmv.
sumber
Apa yang benar-benar diperlukan untuk menyelesaikan ini adalah mekanisme antrian dari beberapa jenis.
Apakah mungkin untuk memiliki pekerjaan membaca input mereka dari Antrian, seperti antrian pesan SYSV, dan kemudian memiliki program yang dijalankan secara paralel hanya dengan mendorong nilai-nilai ke antrian?
Kemungkinan lain adalah menggunakan direktori untuk antrian, seperti ini:
pending
mv
dari file pertama yang dilihatnya di direktori ke direktori saudarapending
, bernamainprogress
.pending
sumber
menguraikan jawaban @ ash, Anda dapat menggunakan antrian pesan SYSV untuk mendistribusikan pekerjaan. Jika Anda tidak ingin menulis program Anda sendiri di C ada sebuah utilitas bernama
ipcmd
yang dapat membantu. Inilah yang saya kumpulkan untuk mengirimkan outputfind $DIRECTORY -type f
ke$PARALLEL
sejumlah proses:Inilah uji coba:
sumber
Kecuali Anda dapat memperkirakan berapa lama file input tertentu akan diproses dan proses pekerja tidak memiliki cara untuk melaporkan kembali ke penjadwal (seperti yang mereka lakukan dalam skenario komputasi paralel paralel - biasanya melalui MPI ), Anda umumnya kurang beruntung - membayar denda dari beberapa pekerja yang memproses input lebih lama dari yang lain (karena ketidaksetaraan input), atau membayar denda karena menelurkan satu proses baru untuk setiap file input.
sumber
GNU Parallel telah berubah dalam 7 tahun terakhir. Jadi hari ini dapat melakukannya:
Contoh ini menunjukkan bahwa lebih banyak blok diberikan pada proses 11 dan 10 daripada proses 4 dan 5 karena 4 dan 5 dibaca lebih lambat:
sumber