터미널에서 멀티 스레드 grep을 시작하는 방법?


38

250GB 이상의 파일이 각각 2GB 인 폴더가 있습니다. 해당 파일에서 문자열 / 패턴을 검색하고 결과를 파일로 출력해야 output합니다. 다음 명령을 실행할 수 있다는 것을 알고 있지만 너무 느립니다 !!

grep mypattern * > output

속도를 높이고 싶습니다. Java의 프로그래머이기 때문에 프로세스 속도를 높이기 위해 멀티 스레딩을 사용할 수 있다는 것을 알고 있습니다. grep"멀티 스레드 모드"에서 시작 하여 출력을 단일 output파일에 쓰는 방법을 고수했습니다 .




1
많은 파일 모음을 검색하는 것이 IO 바운드 문제의 전형적인 예입니다. 따라서 여러 스레드를 사용하면 도움이되지 않습니다.
Jonathan Hartley

답변:


31

이를위한 두 가지 쉬운 솔루션이 있습니다. 기본적으로, 사용 xargs또는 parallel.

xargs 접근법 :

당신은 사용할 수 있습니다 xargs으로 find다음과 같이 :

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

number_of_processes시작하려는 최대 프로세스 수로 대체 할 위치입니다 . 그러나 이는 성능이 I / O 제한 인 경우 중요한 성능을 보장하지 않습니다. 이 경우 I / O 대기 시간 손실을 보상하기 위해 더 많은 프로세스를 시작하려고 할 수 있습니다.

또한 찾기를 포함하면 수정 시간 등과 같은 파일 패턴 대신 고급 옵션을 지정할 수 있습니다.

파일이 적 으면 Stéphane의 의견에 설명 된대로이 접근 방식의 한 가지 가능한 문제는 파일을 xargs충분히 처리하지 못할 수 있습니다. 한 가지 해결책은 -n옵션 을 사용하여 xargs한 번에 파이프에서 몇 개의 인수를 가져야 하는지를 지정하는 것입니다. 설정 -n1하면 xargs각 단일 파일에 대해 새 프로세스가 시작됩니다. 파일이 매우 커서 (이 질문의 경우와 같이) 비교적 적은 수의 파일이있는 경우 이는 바람직한 동작 일 수 있습니다. 그러나 파일 자체가 작 으면 새 프로세스를 시작하는 오버 헤드가 병렬 처리의 이점을 약화시킬 수 있으며,이 경우 더 큰 -n값이 더 좋습니다. 따라서 -n파일 크기 및 수에 따라 옵션이 미세 조정될 수 있습니다.

병렬 접근 :

또 다른 방법은 Ole Tange GNU Parallel 도구 parallel( 여기에서 사용 가능 )를 사용하는 것입니다. 이것은 병렬 처리에 대한 세밀한 제어를 제공하며 여러 호스트에 분산 될 수도 있습니다 (예를 들어, 디렉토리가 공유되는 경우 유리할 것임). 병렬을 사용하는 가장 간단한 구문은 다음과 같습니다.

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

여기서 옵션 -j+1은 머신의 코어 수를 초과하여 하나의 프로세스를 시작하도록 병렬로 지시합니다 (I / O 제한된 작업에 도움이 될 수 있으며 더 많은 수를 시도 할 수도 있습니다).

Parallel은 또한 xargs각 프로세스의 출력 순서를 실제로 유지하고 연속적인 출력을 생성하는 것보다 이점이 있습니다. 예를 들어,을 사용하여 xargs프로세스 1이 say say p1L1를 생성하고 프로세스 2가 line을 생성하고 p2L1프로세스 1이 다른 line을 생성 p1L2하면 출력은 다음과 같습니다.

p1L1
p2L1
p1L2

반면 parallel출력은 다음과 같아야합니다.

p1L1
p1L2
p2L1

이것은 일반적으로 xargs출력 보다 유용 합니다.


1
-n와 함께 사용하고 싶을 것입니다 -P. 그렇지 않으면 xargs두 개의 파일이 몇 개 있으면 여러 프로세스가 생성되지 않을 수 있습니다.
Stéphane Chazelas

1
-n1은 grep파일 당 하나씩 시작 합니다. 파일이 매우 크지 않고 파일이 매우 적은 경우가 아니라면 파일을 검색하는 대신 grep 프로세스를 시작하고 중지하는 데 시간을 할애하여 약간만 늘리고 싶을 것입니다.
Stéphane Chazelas

9

grep CPU 속도를 높이는 최소한 두 가지 방법이 있습니다.

  • 정규식이 아닌 고정 문자열을 검색하는 경우 -F플래그를 지정하십시오 .

  • 패턴이 ASCII 전용 인 경우 UTF-8 대신 8 비트 로케일을 사용하십시오 (예 :) LC_ALL=C grep ....

하드 드라이브에 병목 현상이 발생하더라도 도움이되지 않습니다. 이 경우 아마도 병렬화가 도움이되지 않습니다.


1
방금 man grep"egrep 또는 fgrep 중 하나로서의 직접 호출은 더 이상 사용되지 않지만이 응용 프로그램에 의존하는 기록 응용 프로그램은 수정되지 않은 상태로 실행될 수 있도록 제공됩니다." 이것이 실제로 중요하지는 않지만 다음과 동일합니다.grep -F
iyrin

1
또한 "패턴이 아니라"라고 말할 때 정규 표현식을 말하는 것입니까?
iyrin

"ASCII 전용"검색은 훨씬 적은 CPU를 사용합니다. 하지만 당신의 의견에 언급 된주의 사항을 읽을 필요가 stackoverflow.com/a/11777835/198219
famzah

3

문제가 I / O 바운드가 아닌 경우 멀티 코어 처리에 최적화 된 도구를 사용할 수 있습니다.

sift ( http://sift-tool.org , 면책 조항 : 나는이 도구의 저자입니다) 또는 silver searcher ( https://github.com/ggreer/the_silver_searcher )를 보고 싶을 것 입니다.

단순한 문자열 검색이 아닌 정규식 패턴을 사용하는 경우 silver searcher의 파일 크기 제한은 2GB입니다.


분명히 많은 파일을 검색하는 것이 IO 바인딩 문제의 전형적인 예입니까?
Jonathan Hartley
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.