并行运行命令,但限制同时运行的命令数量

并行运行命令,但限制同时运行的命令数量

顺序:for i in {1..1000}; do do_something $i; done- 太慢

并联:for i in {1..1000}; do do_something $i& done- 负载太大

如何并行运行命令,但每时刻不超过 20 个实例?

现在通常使用类似的黑客技术for i in {1..1000}; do do_something $i& sleep 5; done,但这不是一个好的解决方案。

更新 2:将接受的答案转换为脚本:http://vi-server.org/vi/parallel

#!/bin/bash

NUM=$1; shift

if [ -z "$NUM" ]; then
    echo "Usage: parallel <number_of_tasks> command"
    echo "    Sets environment variable i from 1 to number_of_tasks"
    echo "    Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
    echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
    exit 1
fi

export CMD="$@";

true ${MAKEOPTS:="-j20"}

cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})

all: \${jobs}

\${jobs}:
        i=\$@ sh -c "\$\$CMD"
EOF

请注意,您必须将“i=”前的 8 个空格替换为 2 个制表符才能使其正常工作。

答案1

GNU 并行是为此而制作的。

seq 1 1000 | parallel -j20 do_something

它甚至可以在远程计算机上运行作业。以下是使用 server2 和本地计算机将 MP3 重新编码为 OGG 的示例,每个 CPU 核心运行 1 个作业:

parallel --trc {.}.ogg -j+0 -S server2,: \
     'mpg321 -w - {} | oggenc -q0 - -o {.}.ogg' ::: *.mp3

在这里观看 GNU Parallel 的介绍视频:

http://www.youtube.com/watch?v=OpaiGYxkSuQ

答案2

这不是 bash 解决方案,但您应该使用 Makefile,并且可能-l不会超过某个最大负载。

NJOBS=1000

.PHONY = jobs
jobs = $(shell echo {1..$(NJOBS)})

all: $(jobs)

$(jobs):
    do_something $@

然后一次启动 20 个作业

$ make -j20

或者在不超过 5 个负载的情况下启动尽可能多的作业

$ make -j -l5

答案3

一个简单的想法:

检查 i 模 20,并在 do_something 之前执行 wait shell 命令。

答案4

您可以用ps它来计算正在运行的进程数,每当该数低于某个阈值时,您就启动另一个进程。

伪代码:

i = 1
MAX_PROCESSES=20
NUM_TASKS=1000
do
  get num_processes using ps
  if num_processes < MAX_PROCESSES
    start process $i
    $i = $i + 1
  endif
  sleep 1 # add this to prevent thrashing with ps
until $i > NUM_TASKS

相关内容