병렬 쉘 루프 done >

많은 파일을 처리하고 싶습니다. 여러 코어가 있으므로 병렬로 처리하고 싶습니다.

for i in *.myfiles; do do_something $i `derived_params $i` other_params; done

나는 Makefile 솔루션을 알고 있지만 명령에는 쉘 globbing 목록에서 인수가 필요합니다. 내가 찾은 것은 :

> function pwait() {
>     while [ $(jobs -p | wc -l) -ge $1 ]; do
>         sleep 1
>     done
> }
>

이를 사용하기 위해서는 작업과 pwait 호출을 모두 한 후 수행해야합니다. 매개 변수는 병렬 프로세스 수를 제공합니다.

> for i in *; do
>     do_something $i &
>     pwait 10
> done

그러나 이것은 잘 작동하지 않습니다. 예를 들어 많은 파일을 변환하는 for 루프로 시도했지만 오류가 발생하여 작업이 취소되었습니다.

zsh 메일 링리스트에 대한 토론이 너무 오래되어서 아직 완료되지 않았다는 것을 믿을 수 없습니다. 그래서 당신은 더 잘 알고 있습니까?



답변

makefile 문제에 대한 좋은 해결책입니다. 이 병렬 실행을 쉘에서 프로그래밍 할 수는 있지만 알다시피 어렵습니다. make의 병렬 구현은 작업 시작 및 종료 감지뿐만 아니라로드 밸런싱도 처리하므로 까다로울 수 있습니다.

globbing의 요구 사항은 장애물이 아닙니다.이를 지원하는 구현이 있습니다. GNU make (와 같은 와일드 카드 확장 $(wildcard *.c)및 쉘 액세스 (예 : $(shell mycommand)자세한 내용은 GNU make 설명서 기능 참조)) makeLinux 의 기본값 이며 대부분의 다른 시스템에서 사용 가능합니다. 다음은 필요에 따라 조정할 수있는 Makefile 스켈레톤입니다.

출처 = $ (와일드 카드 * .src)

모두 : $ (sources : .src = .tgt)

% .tgt : $ .src
    do_something $ <$$ (파생 _ 매개 변수 $ <)> $ @

make -j44 개의 작업을 병렬로 실행하거나 make -j -l3로드를 약 3으로 유지하는 것과 같은 것을 실행 하십시오 .


답변

나는 당신의 파생 주장이 무엇인지 잘 모르겠습니다. 그러나 GNU Parallel http : // www.gnu.org/software/parallel/을 사용하면 CPU 코어 당 하나의 작업을 수행 할 수 있습니다.

find . | parallel -j+0 'a={}; name=${a##*/}; upper=$(echo "$name" | tr "[:lower:]" "[:upper:]");
   echo "$name - $upper"'

파생하고자하는 것이 단순히 .extension을 변경하는 것이라면 {.}가 유용 할 수 있습니다

parallel -j+0 lame {} -o {.}.mp3 ::: *.wav

http://www.youtube.com/watch?v=OpaiGYxkSuQ 에서 GNU Parallel에 대한 소개 비디오를 보십시오.


답변

wait명령을 사용하지 않습니까?

for i in *
do
    do_something $i &
done
wait

루프는 작업을 실행 한 다음 기다렸다가 다음 작업을 수행합니다. 위의 방법으로 문제가 해결되지 않으면 pwait이후에 이동하면 더 잘 작동 할 수 있습니다 done.


답변

왜 아무도 xargs를 언급하지 않았습니까?

정확히 세 개의 주장이 있다고 가정하면,

for i in *.myfiles; do echo -n $i `derived_params $i` other_params; done | xargs -n 3 -P $PROCS do_something

그렇지 않으면 구분 기호를 사용하십시오 (null이 유용합니다).

for i in *.myfiles; do echo -n $i `derived_params $i` other_params; echo -ne "\0"; done | xargs -0 -n 1 -P $PROCS do_something

편집 : 위의 경우 각 매개 변수는 null 문자로 구분되어야하며 xargs -n으로 매개 변수 수를 지정해야합니다.


답변

나는 몇 가지 대답을 시도했다. 스크립트가 필요한 것보다 조금 더 복잡해집니다. 이상적으로 사용 parallel또는 xargsfor 루프가 복잡 내부의 작업이 병렬 공급 크고 긴 줄 파일을 만들 문제가 될 수 있다면 그러나 바람직 할 것이다. 대신 다음과 같이 소스를 사용할 수 있습니다

# Create a test file 
$ cat test.txt
task_test 1
task_test 2

# Create a shell source file 
$ cat task.sh
task_test()
{
    echo $1
}

# use the source under bash -c 
$ cat test.txt | xargs -n1 -I{} bash -c 'source task.sh; {}'
1
2

따라서 문제 해결 방법은 다음과 같습니다.

for i in *.myfiles; echo " do_something $i `derived_params $i` other_params
" >> commands.txt ; done

무언가를 정의하다 do_something.sh

do_something(){
process $1
echo $2
whatever $3 

}

xarg또는로 실행gnu parallel

   cat commands.txt | xargs -n1 -I{} -P8 bash -c 'source do_something.sh; {}'

for 반복의 기능적 독립성이 내포되어 있다고 가정합니다.