파일을 분할하고, 각 부분을 매개변수로 스크립트에 전달하고, 각 스크립트를 병렬로 실행합니다.

파일을 분할하고, 각 부분을 매개변수로 스크립트에 전달하고, 각 스크립트를 병렬로 실행합니다.

10000 단어(한 줄에 한 단어)가 포함된 Words.txt가 있습니다. 5,000개의 문서가 있습니다. 어떤 문서에 어떤 단어가 포함되어 있는지 확인하고 싶습니다(단어 주위의 정규식 패턴 사용). 문서를 grep하고 조회수를 출력하는 script.sh가 있습니다. 나는 (1) 입력 파일을 더 작은 파일로 분할하고 (2) 각 파일을 script.sh에 대한 인수로 제공하고 (3) 모든 파일을 병렬로 실행하고 싶습니다.

내 시도는 다음을 기반으로합니다.지도 시간오류가 발생했습니다.

$parallel ./script.sh ::: split words.txt # ./script.sh: line 22: split: No such file or directory

내 script.sh는 다음과 같습니다

#!/usr/bin/env bash

line 1 while read line
line 2  do
        some stuff
line 22 done < $1

grep 명령이 시작된 디렉터리의 파일을 통해 출력을 디렉터리 루프로 분할할 수 있다고 가정합니다. 하지만 이를 우아하고 간결하게(병렬 처리를 사용하여) 수행하는 방법은 무엇입니까?

답변1

STDIN에서 읽는 중이므로 임시 파일이 필요하지 않을 수도 있습니다. 따라서 실제로 사용할 이유가 없습니다 split. 다음 명령을 사용하여 파일을 삭제합니다 --pipe.

cat words | parallel --pipe -L 1000 -N1 ./script.sh

원하는 것을 grep하는 경우 :

find dir-with-5000-files -type f | parallel -X grep -f words.txt 

너무 커서 메모리에 맞지 않으면 words.txt분할할 수 있습니다.

find dir-with-5000-files -type f | parallel -X "cat words.txt | parallel --pipe grep -f -"

GNU Parallel의 매뉴얼 페이지에는 m개의 정규 표현식 n줄을 가장 효율적으로 잡는 방법이 설명되어 있습니다.https://www.gnu.org/software/parallel/parallel_examples.html#example-grepping-n-lines-for-m-regular-expressions

정규식이 많은 대용량 파일을 grep하는 가장 간단한 솔루션은 다음과 같습니다.

grep -f regexps.txt bigfile

또는 정규식이 고정 문자열인 경우:

grep -F -f regexps.txt bigfile

CPU와 디스크 I/O라는 두 가지 제한 요소가 있습니다. CPU는 측정하기 쉽습니다. grep이 CPU의 90%를 초과하는 경우(예: top 실행 시) CPU가 제한 요소이므로 병렬화가 속도를 높입니다. 그렇지 않은 경우 디스크 I/O가 제한 요소이며 디스크 시스템에 따라 병렬화가 더 빨라질 수도 있고 느려질 수도 있습니다. 확실히 알 수 있는 유일한 방법은 측정하는 것입니다.

CPU가 제한 요소인 경우 정규식을 병렬화해야 합니다.

cat regexp.txt | parallel --pipe -L1000 --round-robin grep -f - bigfile

이는 CPU당 하나의 grep을 시작하고 CPU당 한 번 큰 파일을 읽습니다. 그러나 이 작업은 병렬로 수행되므로 첫 번째 읽기를 제외한 모든 읽기가 RAM에 캐시됩니다. regexp.txt의 크기에 따라 -L1000 대신 --block 10m을 사용하는 것이 더 빠를 수도 있습니다. regexp.txt가 너무 커서 RAM에 맞지 않으면 --round-robin을 제거하고 -L1000을 조정하십시오. 이렇게 하면 빅파일을 더 많이 읽을 수 있습니다.

일부 스토리지 시스템은 여러 블록을 병렬로 읽을 때 성능이 더 좋습니다. 이는 일부 RAID 시스템 및 일부 네트워크 파일 시스템에 해당됩니다. 대용량 파일을 병렬로 읽기:

parallel --pipepart --block 100M -a bigfile grep -f regexp.txt

그러면 빅파일이 100MB 청크로 분할되고 각 청크에 대해 grep이 실행됩니다. bigfile과 regexp.txt를 병렬로 읽으려면 --fifo를 사용하여 두 가지를 결합하십시오.

parallel --pipepart --block 100M -a bigfile --fifo cat regexp.txt \
\| parallel --pipe -L1000 --round-robin grep -f - {}

답변2

split도구를 사용하여 다음을 수행할 수 있습니다.

split -l 1000 words.txt words-

파일을 여러 파일로 분할합니다 words.txt. 각 파일의 이름은 1000줄 이하로 지정해야 합니다.

words-aa
words-ab
words-ac
...
words-ba
words-bb
...

접두사가 생략된 경우( words-위 예에서) 기본 접두사 split로 사용됩니다 .x

생성된 파일을 사용하려면 parallelglob을 사용할 수 있습니다.

split -l 1000 words.txt words-
parallel ./script.sh ::: words-[a-z][a-z]

관련 정보