我一直在尝试使用 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) 我在一个目录中有一堆 PNG 图像。我有一个名为 pngout 的应用程序,我运行它来压缩这些图像。这个应用程序是由我做的脚本调用的。问题是这个脚本一次执行一个,如下所示:
FILES=(./*.png)
for f in "${FILES[@]}"
do
echo "Processing $f file..."
# take action on each file. $f store current file name
./pngout -s0 $f R${f/\.\//}
done
Run Code Online (Sandbox Code Playgroud)
一次只处理一个文件,需要很多时间。运行此应用程序后,我看到 CPU 仅为 10%。所以我发现我可以将这些文件分成 4 个批次,将每个批次放在一个目录中并从四个终端窗口、四个进程中触发 4 个,所以我有四个脚本实例,同时处理这些图像和工作需要 1/4 的时间。
第二个问题是我浪费了时间分割图像和批处理并将脚本复制到四个目录,打开4个终端窗口,bla bla ...
如何用一个脚本做到这一点,而不必分割任何东西?
我的意思是两件事:首先,我如何从 bash 脚本启动一个进程到后台?(只是在最后加&?) 第二:如何在发送第四个任务后停止向后台发送任务并让脚本等待任务结束?我的意思是,只是在一个任务结束时向后台发送一个新任务,始终保持 4 个任务并行?如果我不这样做,循环将向后台发送无数个任务,CPU 将阻塞。
我正在使用xargs一个 python 脚本来处理大约 3000 万个小文件。我希望用来xargs并行化这个过程。我使用的命令是:
find ./data -name "*.json" -print0 |
xargs -0 -I{} -P 40 python Convert.py {} > log.txt
Run Code Online (Sandbox Code Playgroud)
基本上,Convert.py会读入一个小的json文件(4kb),做一些处理并写入另一个 4kb 文件。我在具有 40 个 CPU 内核的服务器上运行。并且此服务器上没有运行其他 CPU 密集型进程。
通过监控 htop(顺便说一句,有没有其他好的方法来监控 CPU 性能?),我发现它-P 40没有预期的那么快。有时所有内核会冻结并在 3-4 秒内几乎降至零,然后恢复到 60-70%。然后我尝试将并行进程的数量减少到-P 20-30,但它仍然不是很快。理想的行为应该是线性加速。对 xargs 的并行使用有什么建议吗?
我必须运行 100 个部分的脚本,同时确保在任何时间点只有 10 个部分并行运行。
下面的脚本将同时触发所有 100 个进程:-
for i in {1..100}
do
nohup ksh my_background_script.ksh -mod ${i} &
done
Run Code Online (Sandbox Code Playgroud)