Loading
2022. 3. 1. 10:59 - lazykuna

GNU Parallel과 Pipe

GNU Parallel과 Pipe

Pipe의 동작 방식

먼저, GNU Parallel이 pipe 기반으로 돌아가기 때문에, pipe에 대하여 간략하게 설명을 하면 좋을 것 같다.

pipe는 어떤 프로그램의 output을 다른 program의 input으로 바꿔주는 역할을 한다. 이런 식으로 쓰고...

command1 | command2 | ... | commandn

그런데, 여기에서 구체적으로 어떤 일이 일어나느냐?라고 묻는다면 정확히 답변하기 어려울지도 모른다.

  • command1의 stdout은 command2의 stdin으로 전달된다.
  • command(n-1)의 stdout은 command(n)의 stdin으로 전달된다.
  • 이 일련의 과정에서, 내부적으로 pipe, dup syscall이 발생하여 pipeline 내의 프로그램들은 서로가 pipe로 연결되게 된다. Linux pipe under the hood 참고
  • pipe에서 수행되는 프로그램들은 동시에 모두 켜져서, stdin에 데이터가 오기를 기다리게 된다. (The processes are started at the same time.)
  • 모든 프로세스들이 종료되면 shell은 command가 끝났을 것으로 간주할 것이다.
  • command2가 먼저 종료되고, command1이 stdout write를 시도할 경우, 이미 끊어진 pipe에 값을 쓰려고 시도하였으므로 SIGPIPE 가 발생하게 된다.

이 과정을 그림으로 나타내면 아래와 같다.

GNU Parallel

이제 본론으로 돌아와서, GNU parallel에 대해서 설명하면, 간단히 말해 shell script를 parallel하게 돌릴 수 있도록 해주는 도구다.

오래전에 Perl로 개발되었는데, 최대한의 성능을 끌어 쓸 수 있으면서도 inline scripting 하기 참 간편하다는 이유로, (들리는 소문에 의하면) Data scientist들에게 사랑받고 있는 듯 하다.

재미있는 건 이 도구를 pipeline으로 아래처럼 구동이 가능하다는 것이다.

# 대충 tar로 파일을 푸는 즉시, 파일에 대한 처리(echo)를 병렬로 수행...
tar xvf foo.tgz | perl -ne 'print $l;$l=$_;END{print $l}' | parallel echo

앞선 command의 결과를 parallel이 가져가서 병렬로 처리한다는 건데, 이게 어떻게 가능한건지 살짝 궁금해서, GNU Parallel 내부 동작 원리를 잠깐 찾아보았다.

Design of GNU Parallel 문서를 보면 아래와 같이 쓰여 있는데, 상당히 보수적으로 만들어진 것으로 보인다.

GNU parallel is designed to be able to run on old systems. That means that it cannot depend on a compiler being installed - and especially not a compiler for a language that is younger than 20 years old.

실제 초창기 코드를 보면 몇줄 되지 않는다. 그리고 그 핵심 로직은 바로 Job Slot에 대한 것이다.

The easiest way to explain what GNU parallel
does is to assume that there are a number of job slots, and when a slot becomes available a job from the queue will be run in that slot.

그렇다면 parallel이 수행하는 일은 명료해진다. pipe를 통해서 parallel이 일을 전달받고, 이 일을 Job Slot에 분배하는 것이 전부다.

별로 상관도 없는 두 개념인 듯 하지만 -_-;;... pipe를 활용한 비교적 단순한 인터페이스에 생각보다 단순한 내부구현인데, 이렇게나 유용할 수 있다는 건 꽤나 재미있는 점인 것 같다.

활용방식은 너무 좋은 예시가 많아서 딱히 나같은 초짜가 소개할 건 없지만, Bioinformatics에서의 활용팁 정리한 내용이 꽤 활용도가 좋고 인상깊어 하이퍼링크로 달아놓았다. 이외에도 GNU Parallel Tutorial에도 기상천외한 활용예시들이 많았다.

# 일일이 하나하나 압축하는 것보다
gzip *.fastq
# parallel을 이용하면 성능 최적화하여 작업이 가능하다.
parallel -j 8 gzip ::: *.fastq
# 이런 식으로 폴더에 들어있는 모든 파일들을 뒤져서 작업할 수도 있을 테고...
find . -name "*.fastq" | parallel gzip

출처