Bagaimana cara memulai grep multi-threaded di terminal?

38

Saya memiliki folder yang memiliki 250+ file masing-masing 2 GB. Saya perlu mencari string / pola dalam file-file itu dan menampilkan hasilnya dalam outputfile. Saya tahu saya bisa menjalankan perintah berikut, tetapi terlalu lambat !!

grep mypattern * > output

Saya ingin mempercepatnya. Menjadi seorang programmer di Java, saya tahu multi-threading dapat digunakan untuk mempercepat proses. Saya terjebak pada bagaimana memulai grepdalam "mode multi-threaded" dan menulis output ke dalam satu outputfile.

Abhishek
sumber
Lihat juga unix.stackexchange.com/q/131535
Stéphane Chazelas
Dan unix.stackexchange.com/q/85789
Stéphane Chazelas
1
Tentunya mencari koleksi file besar adalah contoh klasik dari masalah yang terikat IO. Karenanya menggunakan banyak utas tidak akan membantu.
Jonathan Hartley

Jawaban:

31

Ada dua solusi mudah untuk ini. Pada dasarnya, menggunakan xargsatau parallel.

Pendekatan xargs:

Anda dapat menggunakan xargsdengan findsebagai berikut:

find . -type f -print0  | xargs -0 -P number_of_processes grep mypattern > output

Di mana Anda akan mengganti number_of_processesdengan jumlah maksimum proses yang ingin Anda luncurkan. Namun, ini tidak dijamin untuk memberi Anda kinerja yang signifikan jika kinerja Anda terbatas I / O. Dalam hal ini Anda mungkin mencoba untuk memulai lebih banyak proses untuk mengkompensasi waktu yang hilang menunggu I / Os.

Juga, dengan dimasukkannya find, Anda dapat menentukan opsi lebih lanjut daripada hanya pola file, seperti waktu modifikasi, dll ...

Satu kemungkinan masalah dengan pendekatan ini seperti yang dijelaskan oleh komentar Stéphane, jika ada beberapa file, xargsmungkin tidak memulai cukup banyak proses untuk mereka. Salah satu solusinya adalah dengan menggunakan -nopsi untuk xargsmenentukan berapa banyak argumen yang harus diambil dari pipa sekaligus. Pengaturan -n1akan memaksa xargsuntuk memulai proses baru untuk setiap file tunggal. Ini mungkin perilaku yang diinginkan jika file-file tersebut sangat besar (seperti dalam kasus pertanyaan ini) dan ada sejumlah kecil file. Namun, jika file itu sendiri kecil, overhead memulai proses baru dapat merusak keunggulan paralelisme, dalam hal ini -nnilai yang lebih besar akan lebih baik. Dengan demikian, -nopsi mungkin akan disesuaikan dengan ukuran dan jumlah file.

Pendekatan Paralel:

Cara lain untuk melakukannya adalah dengan menggunakan alat Paralel Ole Tange GNU parallel, (tersedia di sini ). Ini menawarkan kontrol butir yang lebih baik atas paralelisme dan bahkan dapat didistribusikan melalui beberapa host (akan bermanfaat jika direktori Anda dibagikan misalnya). Sintaks paling sederhana menggunakan paralel adalah:

find . -type f | parallel -j+1 grep mypattern

di mana opsi -j+1menginstruksikan paralel untuk memulai satu proses yang melebihi jumlah core pada mesin Anda (Ini dapat membantu untuk tugas-tugas terbatas I / O, Anda bahkan dapat mencoba untuk melangkah lebih tinggi jumlahnya).

Paralel juga memiliki keunggulan dibandingkan xargsdengan benar-benar mempertahankan urutan output dari setiap proses dan menghasilkan output yang berdekatan. Misalnya, dengan xargs, jika proses 1 menghasilkan garis katakan p1L1, proses 2 menghasilkan garis p2L1, proses 1 menghasilkan garis lain p1L2, hasilnya akan menjadi:

p1L1
p2L1
p1L2

sedangkan dengan paralleloutput harus:

p1L1
p1L2
p2L1

Ini biasanya lebih bermanfaat daripada xargsoutput.

Bichoy
sumber
1
Anda mungkin ingin menggunakan -nkombinasi dengan -P. Kalau tidak, xargsmungkin tidak akan menghasilkan beberapa proses jika ada dua file.
Stéphane Chazelas
1
Nah, -n1 akan memulai satu grepper file. Kecuali file-file tersebut sangat besar dan jumlahnya sangat sedikit, Anda mungkin ingin meningkatkannya sedikit karena Anda akan menghabiskan waktu Anda memulai dan menghentikan proses grep daripada mencari dalam file.
Stéphane Chazelas
9

Setidaknya ada dua cara mempercepat grep dari segi CPU:

  • Jika Anda mencari string yang diperbaiki daripada ekspresi reguler, tentukan -Fflagnya;

  • Jika pola Anda hanya ASCII, gunakan lokal 8-bit alih-alih UTF-8, mis LC_ALL=C grep ....

Ini tidak akan membantu meskipun jika hard drive Anda adalah hambatan; dalam hal ini mungkin paralelisasi juga tidak akan membantu.

egmont
sumber
1
Hanya melihat di man grep"Doa langsung karena egrep atau fgrep sudah usang, tetapi disediakan untuk memungkinkan aplikasi historis yang bergantung pada mereka untuk berjalan tanpa dimodifikasi." Tidak yakin ini benar-benar penting, tetapi sama dengangrep -F
iyrin
1
Juga ketika Anda mengatakan "bukan pola", apakah yang Anda maksud adalah ekspresi reguler?
iyrin
Pencarian "ASCII-only" menggunakan CPU yang jauh lebih sedikit. Tetapi Anda perlu membaca peringatan yang disebutkan dalam komentar di stackoverflow.com/a/11777835/198219
famzah
3

Jika masalahnya bukan I / O terikat Anda bisa menggunakan alat yang dioptimalkan untuk pemrosesan multi-core.

Anda mungkin ingin melihat sift ( http://sift-tool.org , penafian: Saya penulis alat ini) atau pencari perak ( https://github.com/ggreer/the_silver_searcher ).

pencari perak memiliki batas ukuran file sebesar 2GB jika Anda menggunakan pola regex dan bukan pencarian string spimple.

svent
sumber
Tentunya mencari banyak file adalah contoh klasik dari masalah yang terikat IO?
Jonathan Hartley