我一直在尝试使用 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" …Run Code Online (Sandbox Code Playgroud) 我对.sh使用脚本在脚本中运行一组任务的区别或优势(如果有的话)感到困惑GNU parallel
例如Ole Tange的回答:
parallel ./pngout -s0 {} R{} ::: *.png
Run Code Online (Sandbox Code Playgroud)
而不是说通过它们循环将它们放在背景中&。
例如froschutz的回答:
#copied from the link for illustration
for stuff in things
do
( something
with
stuff ) &
done
wait # for all the something with stuff
Run Code Online (Sandbox Code Playgroud)
简而言之,它们只是在语法上或实际上不同吗?如果实际上不同,我应该什么时候使用它们?
我一直在使用rsync脚本将一台主机上的数据与另一台主机上的数据同步。数据中有许多小文件,几乎占 1.2TB。
为了同步这些文件,我一直在使用以下rsync命令:
rsync -avzm --stats --human-readable --include-from proj.lst /data/projects REMOTEHOST:/data/
Run Code Online (Sandbox Code Playgroud)
proj.lst 的内容如下:
+ proj1
+ proj1/*
+ proj1/*/*
+ proj1/*/*/*.tar
+ proj1/*/*/*.pdf
+ proj2
+ proj2/*
+ proj2/*/*
+ proj2/*/*/*.tar
+ proj2/*/*/*.pdf
...
...
...
- *
Run Code Online (Sandbox Code Playgroud)
作为测试,我选择了其中的两个项目(8.5GB 数据)并执行了上面的命令。作为一个顺序过程,它需要 14 分 58 秒才能完成。因此,对于 1.2TB 的数据,需要几个小时。
如果我可以rsync并行处理多个进程(使用&,xargs或parallel),它将节省我的时间。
我尝试使用以下命令parallel(在cding 到源目录之后),执行时间为 12 分 37 秒:
parallel --will-cite -j 5 rsync -avzm --stats --human-readable {} REMOTEHOST:/data/ ::: …Run Code Online (Sandbox Code Playgroud) 我有一个 shell 脚本问题,我得到了一个充满输入文件的目录(每个文件包含许多输入行),我需要单独处理它们,将它们的每个输出重定向到一个唯一的文件(也就是 file_1.input 需要在 file_1.output 中捕获,依此类推)。
并行前,我只会遍历目录中的每个文件并执行我的命令,同时执行某种计时器/计数技术以免使处理器不堪重负(假设每个进程都有一个恒定的运行时间)。但是,我知道情况并非总是如此,因此使用类似“并行”的解决方案似乎是无需编写自定义代码即可获得 shell 脚本多线程的最佳方法。
虽然我已经想到了一些方法来并行处理这些文件中的每一个(并允许我有效地管理我的内核),但它们似乎都很笨拙。我有一个我认为非常简单的用例,所以我希望尽可能保持干净(并且并行示例中的任何内容似乎都不是我的问题。
任何帮助,将不胜感激!
输入目录示例:
> ls -l input_files/
total 13355
location1.txt
location2.txt
location3.txt
location4.txt
location5.txt
Run Code Online (Sandbox Code Playgroud)
脚本:
> cat proces_script.sh
#!/bin/sh
customScript -c 33 -I -file [inputFile] -a -v 55 > [outputFile]
Run Code Online (Sandbox Code Playgroud)
更新:阅读下面 Ole 的回答后,我能够为我自己的并行实现将缺失的部分放在一起。虽然他的回答很好,但这是我的补充研究和笔记:
我没有运行我的整个过程,而是从概念证明命令开始,以在我的环境中证明他的解决方案。查看我的两个不同的实现(和注释):
find /home/me/input_files -type f -name *.txt | parallel cat /home/me/input_files/{} '>' /home/me/output_files/{.}.out
Run Code Online (Sandbox Code Playgroud)
使用 find(而不是 ls,会导致问题)在我的输入文件目录中查找所有适用的文件,然后将它们的内容重定向到单独的目录和文件。我上面的问题是读取和重定向(实际脚本很简单),所以用 cat 替换脚本是一个很好的概念证明。
parallel cat '>' /home/me/output_files/{.}.out ::: /home/me/input_files/*
Run Code Online (Sandbox Code Playgroud)
第二个解决方案使用并行的输入变量范式来读取文件,但是对于新手来说,这更加令人困惑。对我来说,使用 find a 和 pipe 很好地满足了我的需求。
在对一些模拟数据进行后处理的较大脚本中,我有以下行:
parallel bnzip2 -- *.bz2
Run Code Online (Sandbox Code Playgroud)
其中,如果我理解parallel正确(我可能没有理解),应该在具有列出的扩展名的所有文件上运行程序的 n 核线程。您可能会注意到我拼错了命令bunzip2。我希望这里有警告或错误消息,但它无声无息地失败了。这是故意的吗?以后我怎么不被这件事咬到?
更新:
我parallel安装的可能与我认为的不同:
> parallel --version`
parallel: invalid option -- '-'
parallel [OPTIONS] command -- arguments
for each argument, run command with argument, in parallel
parallel [OPTIONS] -- commands
run specified commands in parallel
Run Code Online (Sandbox Code Playgroud)
parallel我系统上的手册页提供:
parallel(1) parallel(1)
NAME
parallel - run programs in parallel
....
AUTHOR
Tollef Fog Heen
Run Code Online (Sandbox Code Playgroud)
这似乎不是GNU 版本。
echo 'echo "hello, world!";sleep 3;' | parallel
Run Code Online (Sandbox Code Playgroud)
此命令在完成之前不会输出任何内容。Parallel 的手册页声称:
GNU parallel 确保命令的输出与您按顺序运行命令时得到的输出相同。
我想问题在于措辞:您得到的输出与正常运行时相同,但输出与正常运行时不同。例如--results /dev/stdout,我一直在寻找可以执行此操作的选项,但这不起作用。
我的用例是查看我正在运行的命令的实时进度输出。这不是关于完成了多少任务,哪个并行可以为我显示,而是关于我想单独查看每个命令的进度输出。
我会使用 bash 循环 ( for i in $x; do cmd & done;),但我希望能够使用单个 Ctrl+C 停止所有任务,这并行允许我这样做。
是否可以并行执行此操作?如果没有,是否有其他工具?
所以我有一个while循环:
cat live_hosts | while read host; do \
sortstuff.sh -a "$host" > sortedstuff-"$host"; done
Run Code Online (Sandbox Code Playgroud)
但这可能需要很长时间。我将如何在这个 while 循环中使用 GNU Parallel?
% echo -e '1\n2' | parallel "bash -c 'echo :\$1' '' {}"
:1
:2
% echo -e '1\n2' | parallel bash -c 'echo :\$1' '' {}
%
Run Code Online (Sandbox Code Playgroud)
我希望第二行的行为相同。
是否可以限制 GNU 并行启动的所有进程的内存使用量?我意识到有一些方法可以限制作业的数量,但在不容易提前预测内存使用情况的情况下,调整此参数可能会很困难。
在我的特殊情况下,我在 HPC 上运行程序,其中进程内存有硬限制。例如,如果节点上有 72GB 的可用内存,批处理系统将终止超过 70GB 的作业。我也无法直接将工作生成到交换并将它们保留在那里。
GNU 并行包带有niceload,它似乎允许在进程运行之前检查当前内存使用情况。但是我不确定如何使用它。
我知道 GNU Parallel 缓冲区 std/stderr 因为它不希望作业输出被破坏,但是如果我用 运行我的作业parallel do_something ::: task_1 task_2 task_3,无论如何要立即显示 task_1 的输出,然后在 task_1 完成后,task_2 一直到它的当前输出等
如果 Parallel 不能解决这个问题,有没有其他类似的程序可以解决这个问题?
gnu-parallel ×10
shell-script ×3
shell ×2
bash ×1
files ×1
linux ×1
memory ×1
nice ×1
output ×1
parallelism ×1
quoting ×1
rhel ×1
rsync ×1
scripting ×1
xargs ×1