[unix] 배쉬 FOR 루프 병렬화

GNU Parallel을 사용하여 다음 스크립트, 특히 세 개의 FOR 루프 인스턴스 각각을 병렬화하려고 시도했지만 그럴 수 없었습니다. FOR 루프에 포함 된 4 개의 명령은 직렬로 실행되며 각 루프는 약 10 분이 걸립니다.

#!/bin/bash

kar='KAR5'
runList='run2 run3 run4'
mkdir normFunc
for run in $runList
do 
  fsl5.0-flirt -in $kar"deformed.nii.gz" -ref normtemp.nii.gz -omat $run".norm1.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
  fsl5.0-flirt -in $run".poststats.nii.gz" -ref $kar"deformed.nii.gz" -omat $run".norm2.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
  fsl5.0-convert_xfm -concat $run".norm1.mat" -omat $run".norm.mat" $run".norm2.mat"
  fsl5.0-flirt -in $run".poststats.nii.gz" -ref normtemp.nii.gz -out $PWD/normFunc/$run".norm.nii.gz" -applyxfm -init $run".norm.mat" -interp trilinear

  rm -f *.mat
done



답변

왜 그들을 포크 (일명 배경)하지 않습니까?

foo () {
    local run=$1
    fsl5.0-flirt -in $kar"deformed.nii.gz" -ref normtemp.nii.gz -omat $run".norm1.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
    fsl5.0-flirt -in $run".poststats.nii.gz" -ref $kar"deformed.nii.gz" -omat $run".norm2.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
    fsl5.0-convert_xfm -concat $run".norm1.mat" -omat $run".norm.mat" $run".norm2.mat"
    fsl5.0-flirt -in $run".poststats.nii.gz" -ref normtemp.nii.gz -out $PWD/normFunc/$run".norm.nii.gz" -applyxfm -init $run".norm.mat" -interp trilinear
}

for run in $runList; do foo "$run" & done

확실하지 않은 경우 중요한 부분은 다음과 같습니다.

for run in $runList; do foo "$run" & done
                                   ^

백그라운드에서 분기 쉘에서 함수가 실행되도록합니다. 그것은 평행입니다.


답변

샘플 작업

task(){
   sleep 0.5; echo "$1";
}

순차적 실행

for thing in a b c d e f g; do 
   task "$thing"
done

병렬 런

for thing in a b c d e f g; do 
  task "$thing" &
done

N- 프로세스 배치에서 병렬 실행

N=4
(
for thing in a b c d e f g; do 
   ((i=i%N)); ((i++==0)) && wait
   task "$thing" & 
done
)

또한 FIFO를 세마포어로 사용하고 가능한 빨리 새로운 프로세스가 생성되고 동시에 N 개의 프로세스 만 실행되도록하기 위해이를 사용할 수 있습니다. 그러나 더 많은 코드가 필요합니다.

FIFO 기반 세마포어로 N 프로세스 :

open_sem(){
    mkfifo pipe-$$
    exec 3<>pipe-$$
    rm pipe-$$
    local i=$1
    for((;i>0;i--)); do
        printf %s 000 >&3
    done
}
run_with_lock(){
    local x
    read -u 3 -n 3 x && ((0==x)) || exit $x
    (
     ( "$@"; )
    printf '%.3d' $? >&3
    )&
}

N=4
open_sem $N
for thing in {a..g}; do
    run_with_lock task $thing
done 


답변

for stuff in things
do
( something
  with
  stuff ) &
done
wait # for all the something with stuff

실제로 작동하는지 여부는 명령에 따라 다릅니다. 나는 그들에게 익숙하지 않다. 는 rm *.mat이 병렬로 실행되는 경우 충돌하는 경향이 조금 보이는 …


답변

for stuff in things
do
sem -j+0 ( something
  with
  stuff )
done
sem --wait

이것은 사용 가능한 코어 수만큼 반복을 병렬화하는 세마포어를 사용합니다 (-j +0은 N + 0 작업을 병렬화 함을 의미합니다 . 여기서 N은 사용 가능한 코어 수임 ).

sem –wait 는 for 루프의 모든 반복이 실행을 종료 할 때까지 기다렸다가 연속적인 코드 행을 실행하도록 지시합니다.

참고 : GNU 병렬 프로젝트 (sudo apt-get install parallel) 에서 “병렬”이 필요합니다 .


답변

내가 자주 사용하는 한 가지 쉬운 방법 :

cat "args" | xargs -P $NUM_PARALLEL command

이 명령은 동시에 최대 $ NUM_PARALLEL을 실행하면서 “args”파일의 각 줄을 병렬로 전달하여 명령을 실행합니다.

다른 위치에서 입력 인수를 대체해야하는 경우 xargs의 -I 옵션을 살펴볼 수도 있습니다.


답변

fsl 작업은 서로 종속되어 있으므로 4 개의 작업을 병렬로 실행할 수 없습니다. 그러나 런은 병렬로 실행될 수 있습니다.

bash 함수를 단일 실행으로 만들고 해당 함수를 병렬로 실행하십시오.

#!/bin/bash

myfunc() {
    run=$1
    kar='KAR5'
    mkdir normFunc
    fsl5.0-flirt -in $kar"deformed.nii.gz" -ref normtemp.nii.gz -omat $run".norm1.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
    fsl5.0-flirt -in $run".poststats.nii.gz" -ref $kar"deformed.nii.gz" -omat $run".norm2.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 
    fsl5.0-convert_xfm -concat $run".norm1.mat" -omat $run".norm.mat" $run".norm2.mat"
    fsl5.0-flirt -in $run".poststats.nii.gz" -ref normtemp.nii.gz -out $PWD/normFunc/$run".norm.nii.gz" -applyxfm -init $run".norm.mat" -interp trilinear
}

export -f myfunc
parallel myfunc ::: run2 run3 run4

자세한 내용은 인트로 비디오 시청 : https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1을 하고 튜토리얼을 걷는 시간을 보내고 http://www.gnu.org/software/parallel/parallel_tutorial.html 당신의 명령 라인은 당신을 사랑합니다.


답변

최대 N- 프로세스 동시 병렬 실행

#!/bin/bash

N=4

for i in {a..z}; do
    (
        # .. do your stuff here
        echo "starting task $i.."
        sleep $(( (RANDOM % 3) + 1))
    ) &

    # allow only to execute $N jobs in parallel
    if [[ $(jobs -r -p | wc -l) -gt $N ]]; then
        # wait only for first job
        wait -n
    fi

done

# wait for pending jobs
wait

echo "all done"