Последовательный: 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
Обратите внимание, что вы должны заменить 8 пробелов на 2 табуляции перед "i =", чтобы это работало.
parallel
in moreutils не является GNU Parallel и довольно ограничен в своих возможностях. Команда выше не будет работать с параллелью из moreutils.xargs --max-procs=20
.Не bash-решение, но вы должны использовать Makefile, возможно,
-l
чтобы он не превышал какую-то максимальную нагрузку.Затем, чтобы начать 20 работ одновременно
или начать как можно больше заданий, не превышая нагрузку 5
источник
echo -e 'PHONY=jobs\njobs=$(shell echo {1..100000})\n\nall: ${jobs}\n\n${jobs}:\n\t\techo $@; sleep `echo $$RANDOM/6553 | bc -l`' | make -f - -j20
Теперь это выглядит более хакерским снова.размещение сценария в вопросе с форматированием:
Обратите внимание, что перед «i =» вы должны заменить 8 пробелов на 2 табуляции.
источник
Одна простая идея:
Проверьте по модулю 20 и выполните команду оболочки shell перед do_something.
источник
Вы можете использовать,
ps
чтобы подсчитать, сколько процессов у вас запущено, и всякий раз, когда это падает ниже определенного порога, вы запускаете другой процесс.Псевдокод:
источник
источник
while [ `jobs | wc -l` -ge 20]; do
?njobs
дважды вычислить , и производительность довольно важна для сценариев оболочки, которые запускаютsleep 1
на,sleep 0.1
и он начинает усреднять njobs до 40-50 вместо 20. Если существует более 20 рабочих мест, нам нужно дождаться окончания любой работы, а не просто ждать 1 секунду.Вы можете сделать это так.
используя именованные каналы, каждый раз он запускает 20 вспомогательных оболочек параллельно.
Надеюсь, это поможет :)
источник