파이프 된 명령을 병렬로 실행


16

다음 시나리오를 고려하십시오. 두 개의 프로그램 A와 B가 있습니다. 프로그램 A는 stdout 문자열로 출력하는 반면 프로그램 B는 stdin에서 라인을 처리합니다. 이 두 프로그램을 사용하는 방법은 물론입니다.

foo @ bar : ~ $ A | 비

이제 나는 이것이 하나의 핵심만을 먹는다는 것을 알았습니다. 따라서 궁금합니다.

프로그램 A와 B가 동일한 계산 리소스를 공유하고 있습니까? 그렇다면 A와 B를 동시에 실행할 수있는 방법이 있습니까?

내가 알았던 또 다른 것은 A가 B보다 훨씬 빠르게 실행된다는 것입니다. 따라서 더 많은 B 프로그램을 실행할 수 있고 A가 병렬로 출력하는 라인을 처리 할 수 ​​있는지 궁금합니다.

즉, A는 해당 행을 출력하고,이 행을 먼저 읽고 (누가 먼저 읽든지) 프로그램을 처리하고 stdout에서 출력하는 N 개의 프로그램 B가 있습니다.

마지막 질문은 다음과 같습니다.

경쟁 조건 및 잠재적으로 발생할 수있는 다른 불일치를 처리하지 않고 여러 B 프로세스 중 출력을 A로 파이프하는 방법이 있습니까?


1
A | B | C파이프의 특성으로 인해 (B는 A의 출력을 기다려야하고, C는 B의 출력을 기다려야 함) 파이프의 특성으로 인해 별도의 프로세스와 마찬가지로 병렬 이지만 일부 경우에는 여전히 선형 일 수 있습니다. 그것은 전적으로 그들이 어떤 종류의 생산을하는지에 달려 있습니다. 여러 개를 실행하면 많은 B도움 이되는 경우가 많지 않지만 병렬 wc 예제가 일반보다 느리게 wc진행될 수 있습니다. 분할은 정상적으로 라인 수를 계산하는 것보다 더 많은 리소스를 소비 할 수 있습니다. 주의해서 사용하십시오.
frostschutz 2016 년

답변:


14

문제 split --filter는 출력이 섞일 수 있기 때문에 프로세스 1에서 절반을, 프로세스 2에서 절반을 얻는다는 것입니다.

GNU Parallel은 믹스 업이 없음을 보증합니다.

따라서 당신이하고 싶다고 가정하십시오.

 A | B | C

그러나 B는 매우 느리기 때문에 병렬화하고 싶습니다. 그럼 당신은 할 수 있습니다 :

A | parallel --pipe B | C

GNU Parallel은 기본적으로 \ n과 1MB의 블록 크기로 나뉩니다. --recend 및 --block을 사용하여 조정할 수 있습니다.

GNU Parallel에 대한 자세한 내용은 http://www.gnu.org/s/parallel/을 참조하십시오.

다음을 사용하여 10 초만에 GNU Parallel을 설치할 수 있습니다.

wget -O - pi.dk/3 | sh 

http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 의 소개 동영상을 보십시오.


1
귀하의 솔루션이 대부분의 문제를 해결하기 때문에 설치 방법 :-), +1에 동의하지 않습니다.
LSerni 2016 년

이것은 참으로 좋습니다. 사용할 매개 변수에 대한 제안 사항이 있습니까? 프로그램 A가 분당 약 5GB의 1TB 이상의 데이터를 출력한다는 것을 알고 있습니다. 프로그램 B는 A 출력보다 5 배 느린 데이터를 처리 하며이 작업을 위해 5 코어를 처리합니다.
Jernej 2016 년

GNU Parallel은 현재 최대 100MB / s를 처리 할 수 ​​있으므로이 한계에 닿게됩니다. 최적 --block-size의 용량은 RAM의 양과 새로운 시작 속도에 따라 다릅니다 B. 귀하의 상황에서 나는 그것을 어떻게 사용 --block 100M했는지 보았습니다.
Ole Tange

@lserni 대부분의 UNIX 시스템에서 작동하며 사용자와 비슷한 양의 작업이 필요한 더 나은 설치 방법을 생각해 낼 수 있습니까?
Ole Tange

4
미안, 나는 나 자신을 명확히하지 않았다. 설치 방법-스크립트가 전달되었습니다 sh-훌륭합니다. 문제는 그것을 sh로 전달하는 것입니다 : 사이트에서 실행 코드 다운로드 및 실행 . 사용자가 만든 RPM 또는 DEB가 기본적으로 같은 것을 반대 할 수 있고 복사 및 붙여 넣을 페이지에 코드를 게시해도 사람들이 맹목적으로 결과를 초래할 수 있기 때문에 아마도 편집증이 될 수 있습니다. 어쨌든.
LSerni

13

쓰면 A | B두 프로세스가 이미 병렬로 실행됩니다. 하나의 코어 만 사용하는 것으로 보이면 CPU 선호도 설정 중 하나 (아마 선호도가 다른 프로세스를 생성하는 도구가 있음)이거나 하나의 프로세스로 전체 코어를 보유하기에 충분하지 않기 때문일 수 있습니다. 컴퓨팅을 퍼 뜨리지 않는 것이 좋습니다.

하나와 여러 B의를 실행하려면, 당신은 같은 도구가 필요 split--filter옵션 :

A | split [OPTIONS] --filter="B"

그러나 B 작업이 모두 같은 속도로 실행되지 않기 때문에 출력에서 ​​줄 순서를 엉망으로 만들 수 있습니다. 이것이 문제인 경우, i 번째 출력을 중간 파일로 경로 재지 정하고를 사용하여 마지막에 함께 연결해야합니다 cat. 따라서 상당한 디스크 공간이 필요할 수 있습니다.

다른 옵션이 존재 (B의의 전체 "라운드"가 완료 A는, a의 동등한를 실행할 때까지 대기는 예를 들어 단일 라인 버퍼 출력 B의 각 인스턴스를 제한 할 수 감소split지도cat임시 출력 함께) 다양한 수준의 효율성. 예를 들어 방금 설명한 'round'옵션 은 B가장 느린 인스턴스 가 완료 될 때까지 대기 하므로 B에 사용 가능한 버퍼링에 크게 의존합니다. [m]buffer작업이 무엇인지에 따라 도움이 될 수도 있고 아닐 수도 있습니다.

처음 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, split상기 wc프로세스 코어를 공유하고; 그러나 자세히 살펴보면 시스템은 처음 두 프로세스를 CPU0에두고 작업자 프로세스간에 CPU1을 나눕니다.

%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가보다 무거운 프로세스 seq인 경우 상대적 오버 헤드 split가 줄어 듭니다. 그러나 A가 매우 가벼운 프로세스이고 B가 매우 빠르면 (A와 함께 유지하기 위해 2-3B를 넘지 않아도 됨) 병렬 처리 split(또는 일반적으로 파이프) 그만한 가치가 없을 수 있습니다.


우분투에서 발견 된 스플릿에는 --filter 옵션이 없습니다. 이를 위해 어떤 종류의 OS를 사용하고 있습니까?
Jernej 2016 년

coreutils ( gnu.org/software/coreutils/manual/html_node/… )가 있는 Linux OpenSuSE 12.3 우분투를 잡으려고 노력할 것입니다. 비슷한 이름의 도구를 수용하기 위해 이름을 변경했을 수도 있습니다.
LSerni

당신은에 대한 확신 split --filter없는 옵션? 내 우분투 12.04-LTS ( "wheezy / sid")에는 거기 있으며 내 예제가 작동합니다. splitGNU coreutils와 다른 것을 설치할 수 있습니까?
LSerni 2016 년

고마워 최신 버전의 Coreutils를 설치해야했습니다. BTW, 나는 프로그램 A를 단독으로 실행하면 A를 실행하면 전체 코어 (100 %)를 먹는 것으로 나타났습니다. 그런 다음 그들은 함께 전체 코어를 먹고 A를 15 % 먹으며 B를 85 % 먹습니다. 왜 그렇게되는지 아십니까?
Jernej 2016 년

2
차단 때문일 수 있습니다. B가 A보다 무거 우면 A는 출력을 보낼 수 없으며 속도가 느려집니다. 또 다른 가능성은 A 가 작동하는 동안 B에게 양보 하는 것입니다 (예 : 디스크 / 넷). 다른 시스템에서는 B가 CPU1의 100 %를 차지하고 A가 CPU0의 18 %를 할당받는 것을 볼 수 있습니다. 단일 A 인스턴스가 단일 코어를 포화 시키려면 85/15 ~ 5.67 = B의 5-6 인스턴스 사이가 필요할 것입니다. 그러나 I / O가 있으면이 값이 왜곡 ​​될 수 있습니다.
LSerni
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.