Выполнение команд параллельно с пределом одновременного количества команд

Последовательный: 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 вкладками прежде чем "я =", чтобы заставить его работать.

23
задан 28.09.2014, 21:41

6 ответов

Параллель GNU сделана для этого.

seq 1 1000 | parallel -j20 do_something

Это может даже выполнить задания на удаленных компьютерах. Вот пример для перекодирования MP3 к OGG, использующему server2 и локальный компьютер, выполняющий 1 задание на ядро процессора:

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

Посмотрите вводное видео к Параллели GNU здесь:

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

15
ответ дан 07.12.2019, 09:52

Не решение для удара, но необходимо использовать Make-файл, возможно с -l не превысить некоторую максимальную нагрузку.

NJOBS=1000

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

all: $(jobs)

$(jobs):
    do_something $@

Затем для запуска 20 заданий за один раз делают

$ make -j20

или запустить как можно больше заданий, не превышая загрузку 5

$ make -j -l5
4
ответ дан 07.12.2019, 09:52

регистрация сценария в вопросе с форматированием:

#!/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 вкладками прежде чем "я =".

2
ответ дан 07.12.2019, 09:52

Одна простая идея:

Проверьте, поскольку я по модулю 20 и выполняю команду оболочки ожидания прежде do_something.

1
ответ дан 07.12.2019, 09:52

Вы могли использовать 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
1
ответ дан 07.12.2019, 09:52
for i in {1..1000}; do 
     (echo $i ; sleep `expr $RANDOM % 5` ) &
     while [ `jobs | wc -l` -ge 20 ] ; do 
         sleep 1 
     done
done
1
ответ дан 07.12.2019, 09:52

Теги

Похожие вопросы