Temuan unix yang lebih baik dengan pemrosesan paralel?

43

find(1)Utilitas unix sangat berguna memungkinkan saya untuk melakukan suatu tindakan pada banyak file yang cocok dengan spesifikasi tertentu, misalnya

find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;

Di atas mungkin menjalankan skrip atau alat di atas setiap file XML di direktori tertentu.

Katakanlah skrip / program saya membutuhkan banyak waktu CPU dan saya memiliki 8 prosesor. Akan lebih baik untuk memproses hingga 8 file sekaligus.

GNU memungkinkan untuk pemrosesan pekerjaan paralel dengan -jbendera tetapi findtampaknya tidak memiliki fungsi seperti itu. Apakah ada metode penjadwalan pekerjaan generik alternatif untuk mendekati ini?

PP
sumber

Jawaban:

65

xargsdengan -Popsi (jumlah proses). Katakanlah saya ingin mengompres semua file log dalam direktori pada mesin 4-cpu:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2

Anda juga bisa mengatakan -n <number>jumlah unit kerja maksimum per proses. Jadi katakan saya punya 2500 file dan saya berkata:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2

Ini akan memulai 4 bzip2proses, masing-masing dengan 500 file, dan kemudian ketika yang pertama selesai akan dimulai untuk 500 file terakhir.

Tidak yakin mengapa jawaban sebelumnya menggunakan xargs dan make , Anda memiliki dua mesin paralel di sana!

Gayus
sumber
7
Dengan find / xargs, berhati-hatilah: temukan default untuk baris baru sebagai pembatas output, tetapi xarg default untuk setiap spasi putih sebagai pembatas input. Gunakan -0 pada keduanya untuk aman, atau beralih ke paralel GNU yang secara default ke baris baru sebagai pembatas input (mencocokkan output find).
ephemient
1
Wow luar biasa! Saya baru saja memeriksa, dan memang benar, xargs memiliki -Popsi!
PP.
Berhati-hatilah dalam menggunakan xargs -P- ia memiliki bug yang tidak pernah diperbaiki untuk mengacaukan output (tidak seperti parallel) setiap kali 2 utas menghasilkan output pada saat yang sama persis ...
Vlad
34

Paralel GNU juga dapat membantu.

find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}

Perhatikan bahwa tanpa -j8argumen, paralleldefault ke jumlah core pada mesin Anda :-)

singkat
sumber
6

Tidak perlu "memperbaiki" find- memanfaatkan makedirinya sendiri untuk menangani paralelisme.

Biarkan proses Anda membuat file log atau file output lainnya, dan kemudian gunakan Makefile seperti ini:

.SUFFIXES:  .xml .out

.xml.out:
        java -jar ProcessFile.jar $< 1> $@

dan dipanggil demikian:

find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8

Lebih baik lagi, jika Anda memastikan bahwa file output hanya akan dibuat pada penyelesaian proses Java yang berhasil, Anda dapat mengambil keuntungan dari makepenanganan ketergantungan untuk memastikan bahwa lain kali hanya file yang belum diproses yang diselesaikan.

Alnitak
sumber
1
Semoga tidak ada spasi atau karakter "menarik" lainnya dalam nama file itu; Make tidak menangani itu dengan sangat elegan.
ephemient
Ide bagus! Tidak pernah terpikir untuk menggunakan makefile seperti ini.
oscfri
3

Temukan memiliki opsi paralel yang dapat Anda gunakan secara langsung menggunakan simbol "+"; tidak diperlukan xarg. Menggabungkannya dengan grep, dapat menembus pohon Anda dengan cepat mencari korek api. misalnya, jika saya mencari semua file di direktori sumber saya yang berisi string 'foo', saya dapat meminta
find sources -type f -exec grep -H foo {} +

Mark Evans
sumber
12
Membaca manual find, Anda dapat melihat bahwa -exec command +sintaks tidak menjalankannya secara paralel, tetapi "kelompokkan" banyak file bersama dan jalankan perintah dengan beberapa file sebagai argumen pada saat bersamaan. Kebetulan grep dapat melihat targetnya secara paralel.
Gyscos