쉘 스크립트 다중 코어.

제목은 거창한데 실제 구현하고자 하는 것은 동시에 여러 프로세스를 실행하는 것이다. 여러 CPU를 동시에 사용하는 프로그램으로 제작된 것이 아닌 이상 다중 코어 기반의 현재 CPU에서는 idle CPU를 줄이는 것이 시간을 아끼는 일이고, 퇴근 시간과 연구 시간을 줄이는 것이다. bfconvert를 이용하고 있는 지금의 나에게는 파일 변환 시간을 줄이는 것이다. SVS 파일을 4000×4000 pixel로 분할하는 작업을 실행하면 CPU는 100% 정도 밖에 되지 않는다. 나머지 코어 5개 분량은 놀고 있는 것이다. SVS 파일을 통째로 TIFF로 변환하면 250% 정도로 상승하지만 여전히 노는 CPU 자원이 생긴다. 그래서 원하는 수준으로 적당히 여러개를 실행할 수 있는 것이 필요하다.

실행에 시간이 짧게 걸리거나 시스템에 부하가 많이 없다면 한 번에 다 실행하는 방법도 좋을지 모르겠다. 이 방법은 반복문에서 실행 부분에 &를 붙여 모두 백그라운드에서 실행하게 하면 된다.

먼저 알아두어야 할 것은 bfconvert는 실행하면 1초쯤 후에 java 프로세스로 실행이 된다.

나의 목표는 동시에 2 ~3개 정도에서 조절해 보는 것이다. 여러 방법 중에서 조건문 if와  wait를 이용해 보기로 했다. 여유있게 하나 실행하고 10초후에 다시 판정하는 방법을 이용했다. 기다리지 않으면 앞서 언급한 시간차(?)로 인해서 목표한 2개가 아닌 3개가 실행되는 사태가 생긴다. 처음에 if 의 조건문이 자꾸 오류가 나서 찾아본 결과, 대괄호에 띄어쓰기가 필요하다는 것을 알았다.

이 방법은 좋은데 백그라운드로 2개가 동시에 실행되고 있는 경우, 2개가 모두 종료되어야 3번째가 실행이 된다. 그리고 bfconvert는 2번째 변환되는 파일은 속도가 좀 느려진다. 1번째 파일의 변환이 끝나면, 2번째 파일이 혼자 변환되는 것이다.

for file in $file_list; do
  child_proc=`ps -e | grep java | wc -l`
  if [ "${child_proc}" -eq 2 ]; then
  wait
  fi
  file=`basename $file .svs`
  ~/bftools/bfconvert -series 0 -bigtiff ${file}.svs converted/${file}.tif &
  sleep 10
done

계속 2개를 유지시키기 위하여 if 를 기반으로 한 조건문을 여러 번 변경해 보았는데 잘 되지 않았다. 그래서 방법을 좀 바꾸어서 무한 반복 while을 이용해 보기로 했다. 하나씩 계속 실행하다가 실행중인 java 프로세스가 2개 이상이면 일단 60초 대기 후 다시 java 프로세스 숫자 확인한다. 하나가 종료되었다면 while 구문에서 벗어나서 새롭게 변환 프로세스를 실행하는 방식이다. 쉘 스크립트의 숫자 판별식이 등호나 부등호를 이용하지 않기 때문에 매우 적응이 안되는데, 본인의 시스템에 맞는 적절한 숫자와 조건을 이용하면 될 것이다.

for file in $file_list; do
  file=`basename $file .svs`
  ~/bftools/bfconvert -series 0 -bigtiff ${file}.svs converted/${file}.tif &
  sleep 10
  while :
    do
    child_proc=`ps -e | grep java | wc -l`
    if [ "${child_proc}" -lt 2 ]; then
    break
    fi
  sleep 60
  done
done