Bash에 루프가 있다고 가정 해 보겠습니다.
for foo in `some-command`
do
do-something $foo
done
do-something
CPU에 묶여 있고 멋진 4 코어 프로세서가 있습니다. do-something
한 번에 최대 4 개까지 실행하고 싶습니다 .
순진한 접근 방식은 다음과 같습니다.
for foo in `some-command`
do
do-something $foo &
done
이 실행됩니다 모두 do-something
한 번에들하지만, 주로 몇 가지 단점이있다 할이-뭔가도 수행 할 몇 가지 중요한 I / O 할 수 있습니다 모든 조금 느려질 수 있습니다 한 번에 있습니다. 다른 문제는이 코드 블록이 즉시 반환되므로 모든 do-something
s가 완료 되면 다른 작업을 수행 할 방법이 없다는 것 입니다.
do-something
한 번에 항상 X 가 실행 되도록이 루프를 어떻게 작성 하시겠습니까?
답변
원하는 작업에 따라 xargs도 도움이 될 수 있습니다 (여기 : pdf2ps로 문서 변환).
cpus=$( ls -d /sys/devices/system/cpu/cpu[[:digit:]]* | wc -w )
find . -name \*.pdf | xargs --max-args=1 --max-procs=$cpus pdf2ps
문서에서 :
--max-procs=max-procs
-P max-procs
Run up to max-procs processes at a time; the default is 1.
If max-procs is 0, xargs will run as many processes as possible at a
time. Use the -n option with -P; otherwise chances are that only one
exec will be done.
답변
GNU Parallel http://www.gnu.org/software/parallel/ 을 사용하면 다음과 같이 작성할 수 있습니다.
some-command | parallel do-something
GNU Parallel은 원격 컴퓨터에서 작업 실행도 지원합니다. 이렇게하면 원격 컴퓨터의 CPU 코어 당 하나씩 실행됩니다. 코어 수가 다른 경우에도 마찬가지입니다.
some-command | parallel -S server1,server2 do-something
고급 예 : 여기 my_script가 실행될 파일 목록이 있습니다. 파일 확장자는 .jpeg 일 수 있습니다. my_script의 출력이 basename.out의 파일 옆에 배치되기를 원합니다 (예 : foo.jpeg-> foo.out). 컴퓨터에있는 각 코어에 대해 my_script를 한 번씩 실행하고 로컬 컴퓨터에서도 실행하려고합니다. 원격 컴퓨터의 경우 파일이 주어진 컴퓨터로 전송되기를 원합니다. my_script가 완료되면 foo.out을 다시 전송하고 원격 컴퓨터에서 foo.jpeg 및 foo.out을 제거하려고합니다.
cat list_of_files | \
parallel --trc {.}.out -S server1,server2,: \
"my_script {} > {.}.out"
GNU Parallel은 각 작업의 출력이 혼합되지 않도록하므로 출력을 다른 프로그램의 입력으로 사용할 수 있습니다.
some-command | parallel do-something | postprocess
더 많은 예를 보려면 동영상을 참조 하세요 . https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
답변
maxjobs = 4 parallelize () { while [$ # -gt 0]; 하다 jobcnt = (`작업 -p`) if [$ {# jobcnt [@]} -lt $ maxjobs]; 그때 뭔가 $ 1 & 시프트 그밖에 수면 1 fi 끝난 기다림 } arg1 arg2 "3 번째 작업에 5 개의 args"arg4 ...
답변
다음은 .bashrc에 삽입 할 수 있고 매일 하나의 라이너에 사용할 수있는 대체 솔루션입니다.
function pwait() {
while [ $(jobs -p | wc -l) -ge $1 ]; do
sleep 1
done
}
이를 사용하기 위해해야 할 일은 &
작업과 pwait 호출 뒤에 놓기 만하면됩니다. 매개 변수는 병렬 프로세스의 수를 제공합니다.
for i in *; do
do_something $i &
pwait 10
done
wait
의 출력을 기다리는 대신 사용 하는 것이 더 jobs -p
좋지만 주어진 작업이 모두 완료 될 때까지 기다리는 확실한 해결책은없는 것 같습니다.
답변
일반 bash 대신 Makefile을 사용한 다음 동시 작업 수를 지정하십시오. make -jX
여기서 X는 한 번에 실행할 작업 수입니다.
또는 wait
( ” man wait
“)를 사용할 수 있습니다 . 여러 하위 프로세스를 시작하고 호출 wait
합니다. 하위 프로세스가 완료되면 종료됩니다.
maxjobs = 10
foreach line in `cat file.txt` {
jobsrunning = 0
while jobsrunning < maxjobs {
do job &
jobsrunning += 1
}
wait
}
job ( ){
...
}
작업 결과를 저장해야하는 경우 결과를 변수에 할당하십시오. wait
변수에 포함 된 내용을 확인한 후 .
답변
루프를 다시 작성하는 대신 병렬화 유틸리티를 사용해보십시오. 나는 xjobs의 열렬한 팬입니다. 저는 항상 xjobs를 사용하여 네트워크를 통해 파일을 대량 복사합니다. 일반적으로 새 데이터베이스 서버를 설정할 때입니다.
http://www.maier-komor.de/xjobs.html
답변
make
명령에 익숙한 경우 대부분의 경우 실행할 명령 목록을 makefile로 표현할 수 있습니다. 예를 들어 각각 * .output을 생성하는 * .input 파일에서 $ SOME_COMMAND를 실행해야하는 경우 makefile을 사용할 수 있습니다.
INPUT = a. 입력 b. 입력 OUTPUT = $ (INPUT : .input = .output) %.출력 입력 $ (SOME_COMMAND) $ <$ @ 모두 : $ (OUTPUT)
그리고 그냥 실행
make -j <번호>
최대 NUMBER 개의 명령을 병렬로 실행합니다.