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"