for ループの並列化

for ループの並列化

for次のコードのループを並列化したいと思います。どうすればいいですか?

#!/bin/bash
N=$1 
n=$2
for (( i=1; i<=$N; i++ )); do
  min=100000000000000  //set min to some garbage value
  for (( j=1; j<=$n; j++ )); do
    val=$(/path/to/a.out)
    val2=`echo $val | bc`  

      if (( $val2 < $min )); then
        min=$val2; 
      fi
  done
  arr=("${arr[@]}" "$min")
done

ベストアンサー1

#!/bin/bash
# set -x # debug version
N=${1:-123}
n=${2:-45}
workers=${workers:-${3:-10}}
((workers < 1)) && ((workers = 1))
((workers > 20)) && ((workers = 20))

((min=100000000000000))  #set min to some garbage value

work() {
  for i in ${*}; do
    for (( j=1; j<=${n}; j++ )); do
      val=$(/path/to/a.out)
      val2=$(echo ${val} | bc)
      (( val2 < min )) && (( min = val2 ));
    done
    echo ${min}
    # # debug version
    # echo ${i} ${j} ${min}
  done
}

# --
arr=($(
  seq ${N} | xargs -n$[N/workers + 1] | while read i; do
    work ${i} &
  done
  wait
))
echo ${arr[*]}
# --

# # debug version
# seq ${N} | xargs -t -n$[N/workers + 1] | while read i; do
#  work ${i} &
# done
# wait

パラメータ化された数のプロセスを作成するときは、常にワーカースレッドを使用し、作成できるワーカースレッドの最大数を制限してください。

xargs -n | while readリストをまとめて繰り返す簡単な方法です。

  • seq1からNまでの数値リストを作成します。
  • xargs -nリストを N/workers+1 バッチに分割します。
    • たとえば、N = 100workers = 10は、最大11個の数字(1から100まで)の10行を生成します。
  • while read i各数値行をお読みください。
  • work ${i} &一連の数字で関数を呼び出すだけですwork${i}

デバッグ用にコメント付きのデバッグコードを追加しました。echoデバッグバージョンに置き換えて、それらの間のコードを# --デバッグバージョンに置き換えることで、一括してどのように機能するかを確認できます。set -xファイルにリダイレクトできるより詳細なデバッグ出力のために、このエントリのコメントを外します。

さまざまなパラメータを使用してデバッグバージョンを実行して、その動作を確認してください。

parallel.sh 223 5 1
parallel.sh 223 5 5
parallel.sh 223 5 10
parallel.sh 223 5 20

min免責事項:このコードはワーカープロセス間で値を同期しません。最小値を得ることはひどいことではありません。これを行うことができます:

parallel.sh 223 5 20 | tr ' ' '\n' | sort -n | head -1

あるいは、スクリプト自体に同じ内容を追加するだけです。

echo ${arr[*]} | tr ' ' '\n' | sort -n | head -1

おすすめ記事