Як запустити багатопотоковий греп в терміналі?


38

У мене папка, що містить 250+ файлів по 2 ГБ кожен. Мені потрібно шукати рядок / шаблон у цих файлах і виводити результат у outputфайл. Я знаю, що можу виконати таку команду, але це занадто повільно !!

grep mypattern * > output

Я хочу це пришвидшити. Будучи програмістом на Яві, я знаю, що багатошвидкісні потоки можуть бути використані для прискорення процесу. Я застряг у тому, як запустити grepв "багатопотоковому режимі" і записати вихід в один outputфайл.




1
Безумовно, пошук великої колекції файлів є класичним прикладом проблеми, пов'язаної з IO. Отже, використання декількох потоків не допоможе.
Джонатан Хартлі

Відповіді:


31

Для цього є два простих рішення. В основному, використовуючи xargsабо parallel.

Підхід xargs:

Ви можете використовувати xargsз findнаступним чином :

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

Де ви заміните number_of_processesмаксимальну кількість процесів, які ви хочете запустити. Однак це не гарантує ваших значних показників у випадку, якщо ваша продуктивність обмежена введенням / виводом. У такому випадку ви можете спробувати запустити більше процесів, щоб компенсувати втрачений час очікування вводу-виводу.

Крім того, за допомогою включення знаходження ви можете вказати більш вдосконалені параметри, а не просто шаблони файлів, наприклад час модифікації тощо.

Одне можливе питання такого підходу, як пояснено коментарями Stéphane, якщо файлів мало, xargsможе не запустити для них достатньо багато процесів. Одним з варіантів буде використання -nпараметра для xargsвизначення кількості аргументів за один раз. Налаштування -n1змусить xargsзапустити новий процес для кожного окремого файлу. Це може бути бажаною поведінкою, якщо файли дуже великі (як у випадку з цим питанням) і є відносно невелика кількість файлів. Однак якщо самі файли невеликі, накладні витрати на початок нового процесу можуть підірвати перевагу паралелізму, і в цьому випадку більша -nвеличина буде кращою. Таким чином, -nопція може бути тонко налаштована відповідно до розмірів та кількості файлів.

Паралельний підхід:

Інший спосіб зробити це - використовувати інструмент Ole Tange GNU Parallel parallel(доступний тут ). Це забезпечує більший контроль над дрібним зерном над паралелізмом і навіть може бути розповсюджений на декількох хостах (було б корисно, якщо, наприклад, поділиться ваш каталог). Найпростішим синтаксисом, що використовує паралель, буде:

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

де параметр -j+1вказує паралельно запускати один процес, що перевищує кількість ядер на вашій машині (Це може бути корисно для обмежених завдань вводу / виводу, ви навіть можете спробувати перейти на більшу кількість).

Паралель також має перевагу перед тим, що xargsфактично зберігати порядок виходу з кожного процесу та генерувати суміжний вихід. Наприклад, xargsякщо, якщо процес 1 породжує скажіть рядок p1L1, процес 2 породжує лінію p2L1, процес 1 породжує інший рядок p1L2, вихід буде:

p1L1
p2L1
p1L2

тоді як з parallelвиходом слід:

p1L1
p1L2
p2L1

Зазвичай це корисніше, ніж xargsвихід.


1
Можливо, ви хочете використовувати -nв поєднанні з -P. В іншому випадку xargsможе не закінчитися нерестування декількох процесів, якщо є два декілька файлів.
Stéphane Chazelas

1
Ну, -n1 запустив би один grepна файл. Якщо файли не дуже великі і їх дуже мало, ви, мабуть, захочете трохи збільшити, оскільки витратите час на запуск і зупинку процесів grep замість пошуку файлів.
Стефан Шазелас

9

Існує щонайменше два способи прискорити роботу процесора:

  • Якщо ви шукаєте виправлений рядок, а не регулярний вираз, вкажіть -Fпрапор;

  • Якщо ваш шаблон призначений лише для ASCII, використовуйте 8-бітну локаль замість UTF-8, наприклад LC_ALL=C grep ....

Це не допоможе, хоча ваш жорсткий диск є вузьким місцем; у цьому випадку, ймовірно, паралелізування теж не допоможе.


1
Щойно побачив у man grep"Прямому виклику, як або egrep, або fgrep є застарілим, але він надається, щоб дозволити історичним програмам, які покладаються на них, працювати без змін". Не впевнений, що це має значення насправді, але це те саме, щоgrep -F
iyrin

1
Крім того, коли ви говорите ", а не візерунок", ви посилаєтесь на регулярний вираз?
ійрін

Для пошуку "лише для ASCII" використовується значно менший процесор. Але ви повинні прочитати застереження , зазначені в коментарях на stackoverflow.com/a/11777835/198219
famzah

3

Якщо проблема не пов'язана з входом / виводом, ви можете використовувати інструмент, оптимізований для багатоядерної обробки.

Ви можете поглянути на просіювання ( http://sift-tool.org , відмова від відповідальності: я є автором цього інструменту) або срібного пошуку ( https://github.com/ggreer/the_silver_searcher ).

у пошукового срібла обмеження розміру файлу становить 2 Гб, якщо ви використовуєте шаблон регулярного вираження, а не пошук рядового рядка.


Безумовно, пошук купи файлів - це класичний приклад проблеми, яка пов'язана з IO?
Джонатан Хартлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.