다음 시나리오를 고려해보세요. A, B 두 가지 프로그램이 있습니다. 프로그램 A는 문자열 줄을 stdout으로 출력하고, 프로그램 B는 stdin의 문자열을 처리합니다. 물론 이 두 프로그램의 사용법은 다음과 같습니다.
foo@bar:~$ A |B
이제 이것이 하나의 코어만 소비한다는 것을 알았으므로 다음과 같은 질문이 있습니다.
프로그램 A와 B는 동일한 컴퓨팅 리소스를 공유합니까? 가능하다면 A와 B를 동시에 실행할 수 있는 방법이 있나요?
내가 알아차린 또 다른 점은 A가 B보다 훨씬 빠르게 실행된다는 것입니다. 따라서 B 프로그램을 더 많이 실행하고 A의 출력 라인을 병렬로 처리하도록 할 수 있는지 궁금합니다.
즉, A는 해당 행을 인쇄하고 해당 행을 읽는 프로그램 B의 N 인스턴스(누가 먼저 읽든 관계없이)를 처리하고 stdout으로 인쇄합니다.
그래서 내 마지막 질문은 다음과 같습니다.
경쟁 조건 및 기타 불일치 가능성에 대해 걱정할 필요 없이 여러 B 프로세스 내에서 출력을 A로 파이프하는 방법이 있습니까?
답변1
한 가지 문제 split --filter
는 출력이 혼합될 수 있으므로 프로세스 1에서 절반 라인을 얻은 다음 프로세스 2에서 절반 라인을 얻게 된다는 것입니다.
GNU Parallel은 혼란을 보장하지 않습니다.
그래서 당신이하고 싶다고 가정 해 봅시다 :
A | B | C
하지만 B는 매우 느리므로 병렬화하려고 합니다. 그러면 다음과 같이 할 수 있습니다:
A | parallel --pipe B | C
GNU 병렬은 기본적으로 블록 크기가 1MB인 \n으로 분할됩니다. --recend 및 --block을 사용하여 조정할 수 있습니다.
GNU Parallel에 대한 자세한 내용은 다음에서 확인할 수 있습니다.http://www.gnu.org/s/parallel/
단 10초 안에 GNU Parallel을 설치할 수 있습니다:
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
소개 영상 보기http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
답변2
을 작성하면 A | B
두 개의 프로세스가 발생합니다.이미병렬로 실행합니다. 하나의 코어만 사용하는 것으로 보인다면 이는 CPU 선호도 설정 때문이거나(다른 선호도를 가진 프로세스를 생성하는 도구가 있을 수 있음) 하나의 프로세스가 전체 코어를 수용할 만큼 크지 않기 때문입니다. "는 분산 컴퓨팅이 아닙니다.
하나의 A로 여러 B를 실행하려면 다음 옵션이 split
포함 된 도구가 필요합니다 .--filter
A | split [OPTIONS] --filter="B"
그러나 이는 B 작업이 동일한 속도로 실행되지 않기 때문에 출력의 줄 순서를 방해할 수 있습니다. 이것이 문제가 되면 Bi 출력을 중간 파일로 리디렉션하여 마지막에 사용해야 할 수도 있습니다 cat
. 이로 인해 상당한 디스크 공간이 필요할 수 있습니다.
다른 옵션도 있습니다. 예를 들어 B의 각 인스턴스를 버퍼링된 출력의 단일 라인으로 제한하고 B의 전체 "회전"이 완료될 때까지 기다린 후 다음과 같은 작업을 실행할 수 있습니다.줄이다split
도착지도, 임시 출력도 포함 cat
), 효율성 수준이 다릅니다. 예를 들어 방금 설명한 "라운드" 옵션은B의 가장 느린 인스턴스[m]buffer
따라서 작업이 무엇인지에 따라 도움이 될 수도 있고 그렇지 않을 수도 있는 B의 사용 가능한 버퍼링에 크게 의존하게 됩니다 .
예
처음 1000개의 숫자를 생성하고 행 수를 병렬로 계산합니다.
seq 1 1000 | split -n r/10 -u --filter="wc -l"
100
100
100
100
100
100
100
100
100
100
행을 "표시"하면 첫 번째 행이 프로세스 #1로 전송되고 다섯 번째 행이 프로세스 #5로 전송되는 방식을 볼 수 있습니다. 게다가 두 번째 프로세스를 생성하는 데 걸리는 시간 동안 split
첫 번째 프로세스는 이미 할당량을 확보하는 데 적합합니다.
seq 1 1000 | split -n r/10 -u --filter="sed -e 's/^/$RANDOM - /g'" | head -n 10
19190 - 1
19190 - 11
19190 - 21
19190 - 31
19190 - 41
19190 - 51
19190 - 61
19190 - 71
19190 - 81
2코어 시스템에서 실행될 때 프로세스 는 코어를 공유 seq
하지만 자세히 살펴보면 시스템은 처음 두 프로세스를 CPU0에 남겨두고 CPU1을 작업자 프로세스에 할당합니다.split
wc
%Cpu0 : 47.2 us, 13.7 sy, 0.0 ni, 38.1 id, 1.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 15.8 us, 82.9 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5314 lserni 20 0 4516 568 476 R 23.9 0.0 0:03.30 seq
5315 lserni 20 0 4580 720 608 R 52.5 0.0 0:07.32 split
5317 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5318 lserni 20 0 4520 572 484 S 14.0 0.0 0:01.88 wc
5319 lserni 20 0 4520 576 484 S 13.6 0.0 0:01.88 wc
5320 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.85 wc
5321 lserni 20 0 4520 572 484 S 13.3 0.0 0:01.84 wc
5322 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5323 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5324 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.87 wc
특히 split
CPU를 많이 사용한다는 점에 유의하세요. 이는 A의 요구 사항에 비례하여 감소합니다. 즉, A가 A보다 무거운 프로세스인 경우 seq
A의 상대적 오버헤드가 split
감소합니다.하지만A가 매우 가벼운 프로세스이고 B가 매우 빠른 경우(따라서 A와 일관성을 유지하기 위해 2-3B 이상이 필요하지 않음) 다음 split
과 병렬화합니다(또는 일반적으로 파이프라인).가능한그럴 가치가 없어.