4개의 작업을 동시에 실행하는 중...어떻게 해야 하나요?

4개의 작업을 동시에 실행하는 중...어떻게 해야 하나요?

내 디렉토리에 PNG 이미지가 많이 있습니다. 이러한 이미지를 압축하기 위해 실행하는 pngout이라는 애플리케이션이 있습니다. 내가 작성한 스크립트에 의해 애플리케이션이 호출됩니다. 문제는 이 스크립트가 다음과 같이 한 번에 하나의 작업을 수행한다는 것입니다.

FILES=(./*.png)
for f in  "${FILES[@]}"
do
        echo "Processing $f file..."
        # take action on each file. $f store current file name
        ./pngout -s0 $f R${f/\.\//}
done

한 번에 하나의 파일만 처리하는 데는 많은 시간이 걸립니다. 이 애플리케이션을 실행한 후 CPU가 10%에 불과하다는 것을 발견했습니다. 그래서 저는 이 파일들을 4개의 배치로 분할하고, 각 배치를 디렉토리에 넣고, 4개의 터미널 창, 4개의 프로세스에서 4개를 트리거할 수 있다는 것을 알았습니다. 따라서 동시에 처리하는 4개의 스크립트 인스턴스가 있었습니다. 이러한 이미지와 작업은 1/4만큼 올라갔습니다.

두 번째 문제는 이미지와 배치를 분할하고 스크립트를 4개의 디렉터리에 복사하고 4개의 터미널 창을 여는 등의 작업에 시간을 낭비했다는 것입니다.

아무것도 분할하지 않고 스크립트로 이를 달성하려면 어떻게 해야 합니까?

내 말은 두 가지를 의미합니다. 첫째, bash 스크립트에서 백그라운드로 프로세스를 시작하는 방법은 무엇입니까? (끝에 &?만 추가하세요.) 둘째: 네 번째 작업을 보낸 후 백그라운드로 작업 전송을 중지하고 스크립트가 작업이 끝날 때까지 기다리게 하려면 어떻게 해야 합니까? 내 말은, 하나의 작업이 끝나면 백그라운드로 새 작업을 보내고 항상 4개의 작업을 병렬로 유지한다는 뜻인가요? 이렇게 하지 않으면 루프가 수많은 작업을 백그라운드로 보내고 CPU가 막히게 됩니다.

답변1

xargs병렬 실행을 지원하는 복제본이 있는 경우 -P간단히 다음을 수행할 수 있습니다.

printf '%s\0' *.png | xargs -0 -I {} -P 4 ./pngout -s0 {} R{}

다른 아이디어에 대해서는 Wooledge Bash 위키에 있습니다.부분프로세스 관리 기사에서 원하는 내용을 정확하게 설명합니다.

답변2

이미 제안된 솔루션 외에도 압축되지 않은 파일에서 압축된 파일을 생성하는 방법을 설명하는 makefile을 생성하고 이를 사용하여 make -j 44개의 작업을 병렬로 실행할 수 있습니다. 문제는 압축된 파일과 압축되지 않은 파일의 이름을 다르게 지정하거나 다른 디렉터리에 저장해야 한다는 것입니다. 그렇지 않으면 합리적인 make 규칙을 작성하는 것이 불가능합니다.

답변3

GNU 병렬이 있는 경우http://www.gnu.org/software/parallel/설치 후 다음을 수행할 수 있습니다.

parallel ./pngout -s0 {} R{} ::: *.png

다음과 같이 간단하게 GNU Parallel을 설치할 수 있습니다.

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

자세히 알아보려면 GNU Parallel 소개 비디오를 시청하세요. https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

답변4

두 가지 질문에 답하려면:

  • 예, 줄 끝에 &를 추가하면 쉘이 백그라운드 프로세스를 시작하도록 지시합니다.
  • wait명령을 사용하면 계속하기 전에 백그라운드의 모든 프로세스가 완료될 때까지 기다리도록 셸에 요청할 수 있습니다.

j다음은 백그라운드 프로세스 수를 추적하기 위해 수정된 스크립트입니다 . 이 값에 도달 하면 NB_CONCURRENT_PROCESSES스크립트는 j0으로 재설정되고 실행을 재개하기 전에 모든 백그라운드 프로세스가 완료될 때까지 기다립니다.

files=(./*.png)
nb_concurrent_processes=4
j=0
for f in "${files[@]}"
do
        echo "Processing $f file..."
        # take action on each file. $f store current file name
        ./pngout -s0 "$f" R"${f/\.\//}" &
        ((++j == nb_concurrent_processes)) && { j=0; wait; }
done

관련 정보