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

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

16
задан ᔕᖺᘎᕊ
04.03.2023 9:47 Количество просмотров материала 2684
Распечатать страницу

7 ответов

GNU Parallel сделано для этого.

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 Parallel здесь:

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

11
отвечен Ole Tange 2023-03-05 17:35

не решение bash, но вы должны использовать Makefile, возможно с -l не превысьте некоторую максимальную нагрузку.

NJOBS=1000

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

all: $(jobs)

$(jobs):
    do_something $@

затем, чтобы начать 20 рабочих мест одновременно

$ make -j20

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

$ make -j -l5
4
отвечен Benjamin Bannier 2023-03-05 19:52

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

проверить I по модулю 20 и выполнить команду wait shell-command перед do_something.

1
отвечен harrymc 2023-03-05 22:09

можно использовать 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
отвечен Paul R 2023-03-06 00:26
for i in {1..1000}; do 
     (echo $i ; sleep `expr $RANDOM % 5` ) &
     while [ `jobs | wc -l` -ge 20 ] ; do 
         sleep 1 
     done
done
1
отвечен msw 2023-03-06 02:43

размещение скрипта в вопросе с форматированием:

#!/bin/bash

NUM=; 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=".

1
отвечен warren 2023-03-06 05:00

вы можете сделать это вот так.

threads=20
tempfifo=$PMS_HOME/$$.fifo

trap "exec 1000>&-;exec 1000<&-;exit 0" 2
mkfifo $tempfifo
exec 1000<>$tempfifo
rm -rf $tempfifo

for ((i=1; i<=$threads; i++))
do
    echo >&1000
done

for ((j=1; j<=1000; j++))
do
    read -u1000
    {
        echo $j
        echo >&1000
    } &
done

wait
echo "done!!!!!!!!!!"

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

надеюсь, что это поможет :)

0
отвечен ouyangyewei 2023-03-06 07:17

Постоянная ссылка на данную страницу: [ Скопировать ссылку | Сгенерировать QR-код ]

Ваш ответ

Опубликуйте как Гость или авторизуйтесь

Имя
Вверх