我正在使用这个脚本来分析数据。
#!/bin/bash
inlist=/aut/cl/tera/mja/scripts
in=/aut/cl/tera/mja/data/ran_ready/
out=/aut/cl/tera/mja/data/mas/aft/
for i in $(cat $inlist/list.txt); do
echo "$i"
mri_binarize --i ${in}/${i}/mri/aseg.mgz --o ${out}/${i}/masks/cc.nii.gz --match 41 42 43 44 45
flirt -in ${out}/${i}/masks/cc.nii.gz -ref ${out}/${i}/T1.nii -out ${out}/${i}/masks/cc2T1.nii.gz -omat ${out}/${i}/masks/cc2T1.mat -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 -interp trilinear
echo "$i ... done"
wait
done
该脚本在 list.txt 中提到的条目列表(50 个条目)上运行两个命令行。对于每个条目,该脚本需要半小时才能完成工作。我想使用以下命令同时对 list.txt 中的所有条目运行此脚本“xargs”或任何其他可能的方式!
我们如何修改这个脚本以使其更加高效?
答案1
如果你有 GNU Parallel,你可以这样做:
doit() {
i=$1
echo "$i"
mri_binarize --i ${in}/${i}/mri/aseg.mgz --o ${out}/${i}/masks/cc.nii.gz --match 41 42 43 44 45
flirt -in ${out}/${i}/masks/cc.nii.gz -ref ${out}/${i}/T1.nii -out ${out}/${i}/masks/cc2T1.nii.gz -omat ${out}/${i}/masks/cc2T1.mat -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 -interp trilinear
echo "$i ... done"
}
export -f doit
parallel doit :::: $inlist/list.txt
这将为每个核心运行 1 个作业。
所有新计算机都具有多个内核,但大多数程序本质上是串行的,因此不会使用多个内核。然而,许多任务是极其可并行化的:
- 在许多文件上运行相同的程序
- 对文件中的每一行运行相同的程序
- 为文件中的每个块运行相同的程序
GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。
如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:
相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:
安装
如果您的发行版未打包 GNU Parallel,您可以进行个人安装,不需要 root 访问权限。这样做可以在 10 秒内完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多示例:http://www.gnu.org/software/parallel/man.html
观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
浏览本教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel
答案2
如果程序并行运行没有任何问题,为什么不简单地将它们发送到后台:
for i in $(cat $inlist/list.txt); do
echo "$i"
(
mri_binarize --i ${in}/${i}/mri/aseg.mgz --o ${out}/${i}/masks/cc.nii.gz --match 41 42 43 44 45
flirt -in ${out}/${i}/masks/cc.nii.gz -ref ${out}/${i}/T1.nii -out ${out}/${i}/masks/cc2T1.nii.gz -omat ${out}/${i}/masks/cc2T1.mat -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 -interp trilinear
echo "$i ... done"
) &
done
括号将命令组合在一起并在子 shell 中运行它们,因此我们可以将命令一起发送到后台。我假设该flirt
命令需要在mri_binarize
.如果没有,只需&
在两个命令后添加一个:
mri_binarize --i ${in}/${i}/mri/aseg.mgz --o ${out}/${i}/masks/cc.nii.gz --match 41 42 43 44 45 &
flirt -in ${out}/${i}/masks/cc.nii.gz -ref ${out}/${i}/T1.nii -out ${out}/${i}/masks/cc2T1.nii.gz -omat ${out}/${i}/masks/cc2T1.mat -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12 -interp trilinear &