Bash:等待固定数量的进程

Bash:等待固定数量的进程

我编写了一个 bash 脚本,用于执行 Java jarn次数。

在实践中,我定义了 e富()函数,包含调用,然后我运行这个脚本:

for RUN in $(seq 1 $RUNS) 
do 
    foo & 
done

现在,我不想执行运行并行的时间。是否有等待限制并行执行的数量(例如wait每 10 个进程)?

答案1

bash4.4 版引入了一个有用的新习惯用法,称为参数变换在这种情况下这可以帮助你。在下面的代码片段中,请注意${num_jobs@P}.这@P是一种类型参数变换这会导致变量像提示字符串一样展开bash。参见man bash其他参数变换选项。

#!/bin/bash
num_procs=$1
num_iters=$2
num_jobs="\j"  # The prompt escape for number of jobs currently running
for ((i=0; i<num_iters; i++)); do
  while (( ${num_jobs@P} >= num_procs )); do
    wait -n
  done
  foo &
done

归功于切普纳https://stackoverflow.com/a/38775799/6631810


根据 Kusalananda 的评论,如果需要,为了使这组进程独立于任何其他会影响计数的后台作业,您可以用它们自己的 shell 来包装它们。为此,需要进行一些更改。

#!/bin/bash
# start a wrapper shell for the group of jobs
cat<<EOS | bash &
num_procs="$1"
num_iters="$2"
for ((i=0; i<num_iters; i++)); do
  # escape what's not supposed to be expanded
  # at the time of here-doc redirection
  while (( \${num_jobs@P} >= num_procs )); do  
    wait -n
  done
  foo &
done
EOS
# now you can do other things

答案2

for RUN in $(seq 1 $RUNS); do
    foo &

    if (( (RUN % 10) == 0 )); then
        wait
    fi
done

或者,使用替代循环构造(恕我直言,看起来更好):

for (( r = 1; r <= RUNS; ++i )); do
    foo &

    if (( (r % 10) == 0 )); then
        wait
    fi
done

如果不是 10 的倍数,您可能还需要wait在循环后添加一个单独的值。$RUNS


除了RUNS运行总数之外,我们还可以想象有n10 个作业的批次:

for (( i = 0; i < n; ++i )); do
    printf 'starting batch %d...\n' "$i"
    for (( j = 0; j < 10; ++j )); do
        foo &
    done

    echo 'waiting...'
    wait
done

xargs使用并且没有显式的替代解决方案wait

seq 1 "$RUNS" | xargs -n 1 -P 10 foo

然而,这会给进程一个可能不需要的foo命令行参数(由 生成的整数之一)。seq这消除了这个问题:

seq 1 "$RUNS" | xargs -n 1 -P 10 sh -c 'foo'

答案3

GNU Parallel 正是为此而设计的:

seq 1 $RUNS | parallel -j 10 -N0 foo

默认情况下,每个 CPU 核心运行一项作业:

seq 1 $RUNS | parallel -N0 foo

GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。

如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:

简单的调度

相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

GNU 并行调度

安装

出于安全原因,您应该使用软件包管理器安装 GNU Parallel,但如果 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

相关内容