Bash:如何简单地并行化任务?

时间:2010-06-09 01:12:00

标签: bash concurrency

我正在编写一个小脚本,在几百个PNG文件上调用“PNGOUT”工具。我只是这样做了:

find $BASEDIR -iname "*png" -exec pngout {} \;

然后我看着我的CPU显示器,注意到只使用了一个核心,这很可悲。

在双核,四核,八核和六核(?)核心桌面的这个时代,我如何简单地将此任务与Bash并行化? (这不是我第一次有这样的需求,因为很多这些工具都是单线程的......我已经有了mp3编码器的情况。)

只需在后台运行所有 pngout 吗?我的发现命令会如何? (我不太确定如何混合查找和'&'字符)

如果我有三百张图片,这意味着要在三百个流程之间进行交换,这看起来不太好!?

或者我应该在“nb dirs”中复制我的三百个文件,其中“nb dirs”将是核心数量,然后同时运行“nb发现”? (这将足够接近)

但我该怎么做?

3 个答案:

答案 0 :(得分:22)

回答我自己的问题......事实证明 xargs 命令的一个相对未知的功能可以用来完成它:

find . -iname "*png" -print0 | xargs -0 --max-procs=4 -n 1 pngout

Bingo,在四核机器上即时加速4倍:)

答案 1 :(得分:4)

在后台生成所有任务:

find $BASEDIR -iname "*png" | while read f; do
  pngout "$f" &
done

但当然这不是最好的选择。一次做'n'个任务:

i=0
find $BASEDIR -iname "*png" | while read f; do
  pngout "$f" &
  i=$((i+1))
  if [[ $i -gt $NTASKS ]]; then
    wait
    i=0
  fi
done

它不是最佳的,因为它等待所有并发任务完成以启动另一个组;但它应该比没有好。

答案 2 :(得分:2)

Parallellization很少是微不足道的。在您的情况下,如果您可以在相同大小的集合中唯一地选择文件,那么您可以运行查找脚本的多个副本。您不想在后台启动300张照片。对于这样的工作,顺序运行它们通常会更快。背景命令或使用批处理都是可行的选择。

假设文件是​​连续编号的,你可以在一个查找中使用类似“ [0-4] .png”的查找模式,在另一个文件中使用“ [5-9] .png”。这将使两个核心运行大致相同的时间。

农业任务将涉及调度员 - 跑步者设置。构建,测试和运行这将花费很长时间。

启动BOINC以使用这些备用处理器。在监视cpu频率时,您可能希望忽略niced进程。将这样的代码添加到rc.local。

for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
    echo 1 > ${CPU}/cpufreq/ondemand/ignore_nice_load
done