디렉토리에 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 개의 터미널 창을 열고 bla bla …
아무것도 나누지 않고 하나의 스크립트로 어떻게합니까?
두 가지 의미 : 먼저 bash 스크립트에서 프로세스를 백그라운드로 실행하려면 어떻게해야합니까? 두 번째 : 네 번째 작업을 보낸 후 백그라운드로 작업 보내기를 중지하고 작업이 끝날 때까지 스크립트를 기다리려면 어떻게해야합니까? 하나의 작업이 끝날 때마다 새로운 작업을 백그라운드로 보내서 항상 4 개의 작업을 병렬로 유지한다는 의미입니까? 내가 그렇게하지 않으면 루프가 수십억 개의 작업을 백그라운드로 시작하고 CPU가 막힙니다.
답변
xargs
와의 병렬 실행을 지원 하는 사본이있는 경우 -P
간단하게 수행 할 수 있습니다
printf '%s\0' *.png | xargs -0 -I {} -P 4 ./pngout -s0 {} R{}
다른 아이디어를 위해 Wooledge Bash 위키에는 프로세스 관리 기사에서 원하는 것을 정확하게 설명 하는 섹션 이 있습니다.
답변
이미 제안 된 솔루션 외에도 압축 파일에서 압축 파일을 작성하고 make -j 4
4 개의 작업을 병렬로 실행 하는 방법을 설명하는 makefile을 작성할 수 있습니다 . 문제는 압축 및 압축되지 않은 파일의 이름을 다르게 지정하거나 다른 디렉토리에 저장해야한다는 것입니다. 그렇지 않으면 합리적인 작성 규칙을 작성하는 것이 불가능합니다.
답변
GNU Parallel 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
답변
두 가지 질문에 대답하려면 :
- 예, 줄의 끝에 &를 추가하면 쉘이 백그라운드 프로세스를 시작하도록 지시합니다.
wait
명령을 사용하면 쉘이 백그라운드의 모든 프로세스가 완료 될 때까지 기다렸다가 계속 진행할 수 있습니다.
j
백그라운드 프로세스 수를 추적하는 데 사용 되도록 수정 된 스크립트는 다음과 같습니다 . 경우 NB_CONCURRENT_PROCESSES
에 도달 할 때 스크립트가 재설정됩니다 j
0과 그것의 실행을 다시 시작하기 전에 모두 완료 될 때까지 백그라운드 프로세스를 기다립니다.
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