Параллельная обработка или потоковая обработка в оболочках

Я пишу script в оболочке, в которой выполняется команда, и занимает 2 минуты. каждый раз. Кроме того, мы ничего не можем с этим поделать. Но если я хочу запустить эту команду 100 раз в script, тогда общее время будет 200мин. и это создаст большую проблему. Никто не хочет ждать 200мин. Я хочу, чтобы запустить все 100 команд параллельно, так что вывод будет в 2 минуты или может быть еще несколько раз, но не займет 200 минут.

будет понятно, если какой-либо орган может мне помочь в этом.

Ответ 1

GNU Parallel - это то, что вы хотите, если вы не хотите изобретать колесо. Вот несколько более подробных примеров, но тем не менее:

ls | parallel gzip # gzip all files in a directory

Ответ 2

... запускать все 100 команд параллельно, чтобы выход поступал в 2 минуты

Это возможно только в том случае, если у вас в вашей системе 200 процессоров.

В командной оболочке script нет такой утилиты/команды для параллельной работы команд. Вы можете выполнить команду в фоновом режиме:

for ((i=0;i<200;i++))
do
   MyCommand &
done

С & (фон) каждое выполнение запланировано как можно скорее. Но это не гарантирует, что ваш код будет выполнен менее чем за 200 минут. Это зависит от количества процессоров в вашей системе.

Если у вас есть только один процессор, и каждое выполнение команды (которая занимает 2 минуты) выполняет некоторое вычисление в течение 2 минут, то процессор выполняет некоторую работу, а это означает, что нет циклов впустую. В этом случае запуск параллельных команд не поможет, потому что есть только один процессор, который также не является бесплатным. Таким образом, процессы будут просто ждать, пока их очередь будет выполнена.

Если у вас несколько процессоров, приведенный выше метод (для цикла) может помочь сократить общее время выполнения.

Ответ 3

Как сказал @KingsIndian, вы можете выполнять фоновые задачи, которые позволяют им работать параллельно. Помимо этого, вы также можете отслеживать их по идентификатору процесса:

#!/bin/bash

# Function to be backgrounded
track() {
  sleep $1
  printf "\nFinished: %d\n" "$1"
}

start=$(date '+%s')

rand3="$(jot -s\  -r 3 5 10)"

# If you don't have `jot` (*BSD/OSX), substitute your own numbers here.
#rand3="5 8 10"

echo "Random numbers: $rand3"

# Make an associative array in which you'll record pids.
declare -A pids

# Background an instance of the track() function for each number, record the pid.
for n in $rand3; do
  track $n &
  pid=$!
  echo "Backgrounded: $n (pid=$pid)"
  pids[$pid]=$n
done

# Watch your stable of backgrounded processes.
# If a pid goes away, remove it from the array.
while [ -n "${pids[*]}" ]; do
  sleep 1
  for pid in "${!pids[@]}"; do
    if ! ps "$pid" >/dev/null; then
      unset pids[$pid]
      echo "unset: $pid"
    fi
  done
  if [ -z "${!pids[*]}" ]; then
    break
  fi
  printf "\rStill waiting for: %s ... " "${pids[*]}"
done

printf "\r%-25s \n" "Done."
printf "Total runtime: %d seconds\n" "$((`date '+%s'` - $start))"

Вы также должны посмотреть документацию Bash на coprocesses.