11

コマンドが実行され、2分かかるシェルでスクリプトを書いています。毎回。また、これについて私たちができることは何もありません。しかし、スクリプトでこのコマンドを 100 回実行したい場合、合計時間は 200 分になります。そしてこれは大きな問題を引き起こします。誰も200分待ちたくない。私が望むのは、100個のコマンドすべてを並列に実行して、出力が2分かかるか、もう少し時間がかかるかもしれませんが、200分かからないようにすることです。

誰かがこれについて何らかの形で私を助けることができれば、それは高く評価されます.

4

3 に答える 3

16

車輪の再発明をしたいのでない限り、GNU Parallelはあなたが望むものです。ここにいくつかのより詳細ながありますが、それは簡単です:

ls | parallel gzip # gzip all files in a directory
于 2012-06-21T04:43:31.990 に答える
13

...出力が2分で来るように、100個のコマンドすべてを並行して実行します

これは、システムに200個のプロセッサがある場合にのみ可能です。

コマンドを並行して実行するためのそのようなユーティリティ/コマンドはシェルスクリプトにはありません。あなたができることは、バックグラウンドでコマンドを実行することです:

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

(バックグラウンド)を使用&すると、各実行ができるだけ早くスケジュールされます。ただし、これはコードが200分未満で実行されることを保証するものではありません。システムに搭載されているプロセッサの数によって異なります。

プロセッサが1つだけで、コマンドの実行ごとに(2分かかる)2分間の計算が行われている場合、プロセッサは何らかの作業を行っています。つまり、無駄なサイクルはありません。この場合、コマンドを並行して実行しても効果はありません。これは、空きではないプロセッサが1つしかないためです。したがって、プロセスは順番が実行されるのを待っているだけです。

複数のプロセッサを使用している場合は、上記の方法(forループ)が合計実行時間を短縮するのに役立つ場合があります。

于 2012-06-18T16:58:56.817 に答える
7

@KingsIndianが言ったように、タスクをバックグラウンドで実行できるため、それらを並行して実行できます。さらに、プロセス ID でそれらを追跡することもできます。

#!/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))"

coprocessesに関する Bash のドキュメントも参照してください。

于 2012-06-18T18:06:59.590 に答える