Rav*_*ill 180 shell-script gnu-parallel
我一直在尝试使用 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
Run Code Online (Sandbox Code Playgroud)
PSk*_*cik 270
task(){
sleep 0.5; echo "$1";
}
Run Code Online (Sandbox Code Playgroud)
for thing in a b c d e f g; do
task "$thing"
done
Run Code Online (Sandbox Code Playgroud)
for thing in a b c d e f g; do
task "$thing" &
done
Run Code Online (Sandbox Code Playgroud)
N=4
(
for thing in a b c d e f g; do
((i=i%N)); ((i++==0)) && wait
task "$thing" &
done
)
Run Code Online (Sandbox Code Playgroud)
也可以使用 FIFO 作为信号量,并使用它们来确保尽快产生新进程并且同时运行不超过 N 个进程。但它需要更多的代码。
# initialize a semaphore with a given number of tokens
open_sem(){
mkfifo pipe-$$
exec 3<>pipe-$$
rm pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
# run the given command asynchronously and pop/push tokens
run_with_lock(){
local x
# this read waits until there is something to read
read -u 3 -n 3 x && ((0==x)) || exit $x
(
( "$@"; )
# push the return code of the command to the semaphore
printf '%.3d' $? >&3
)&
}
N=4
open_sem $N
for thing in {a..g}; do
run_with_lock task $thing
done
Run Code Online (Sandbox Code Playgroud)
我们通过推送 (= printf
) 和弹出 (= read
) 标记 ( '000'
) 来使用文件描述符 3 作为信号量。通过推送已执行任务的返回码,我们可以在出现问题时中止。
gol*_*cks 149
你为什么不分叉(又名背景)它们?
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
Run Code Online (Sandbox Code Playgroud)
如果不清楚,重要的部分在这里:
for run in $runList; do foo "$run" & done
^
Run Code Online (Sandbox Code Playgroud)
导致函数在后台分叉的 shell 中执行。那是平行的。
fro*_*utz 86
for stuff in things
do
( something
with
stuff ) &
done
wait # for all the something with stuff
Run Code Online (Sandbox Code Playgroud)
它是否真的有效取决于你的命令;我对他们不熟悉。的rm *.mat
,如果它在并行运行看起来有点容易产生矛盾?
lev*_*lev 37
for stuff in things
do
sem -j+0 "something; \
with; \
stuff"
done
sem --wait
Run Code Online (Sandbox Code Playgroud)
这将使用信号量,并行化与可用内核数一样多的迭代(-j +0 表示您将并行化N+0 个作业,其中N 是可用内核数)。
sem --wait告诉在执行连续的代码行之前等待 for 循环中的所有迭代都终止执行。
注意:您将需要来自GNU 并行项目的“并行” (sudo apt-get install parallel)。
Tom*_*zka 26
只是一个香草bash脚本-无需外部库/应用需要。
#!/bin/bash
N=4
for i in {a..z}; do
(
# .. do your stuff here
echo "starting task $i.."
sleep $(( (RANDOM % 3) + 1))
) &
# allow to execute up to $N jobs in parallel
if [[ $(jobs -r -p | wc -l) -ge $N ]]; then
# now there are $N jobs already running, so wait here for any job
# to be finished so there is a place to start next one.
wait -n
fi
done
# no more jobs to be started but wait for pending jobs
# (all need to be finished)
wait
echo "all done"
Run Code Online (Sandbox Code Playgroud)
#!/bin/bash
N=4
find ./my_pictures/ -name "*.jpg" | (
while read filepath; do
jpegoptim "${filepath}" &
if [[ $(jobs -r -p | wc -l) -ge $N ]]; then wait -n; fi
done;
wait
)
Run Code Online (Sandbox Code Playgroud)
小智 23
我经常使用的一种非常简单的方法:
cat "args" | xargs -P $NUM_PARALLEL command
Run Code Online (Sandbox Code Playgroud)
这将运行命令,同时传入“args”文件的每一行,最多同时运行 $NUM_PARALLEL。
如果您需要替换不同位置的输入参数,您还可以查看 xargs 的 -I 选项。
Ole*_*nge 10
似乎 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
Run Code Online (Sandbox Code Playgroud)
要了解更多信息,请观看介绍视频:https : //www.youtube.com/playlist? list =PL284C9FF2488BC6D1并花一个小时浏览教程http://www.gnu.org/software/parallel/parallel_tutorial.html您的命令line 会喜欢你的。
小智 6
我真的很喜欢@lev 的答案,因为它以非常简单的方式提供了对最大进程数的控制。但是,如手册中所述, sem 不适用于括号。
for stuff in things
do
sem -j +0 "something; \
with; \
stuff"
done
sem --wait
Run Code Online (Sandbox Code Playgroud)
做这份工作。
-j +N 将 N 添加到 CPU 内核数。并行运行这么多作业。对于计算密集型作业 -j +0 很有用,因为它会同时运行 CPU 核心数的作业。
-j -N 从 CPU 内核数中减去 N。并行运行这么多作业。如果评估的数字小于 1,则将使用 1。另请参阅--use-cpus-instead-of-cores。