顺序: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 的介绍视频:
答案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