Paralelisasi untuk loop


9

Saya ingin memparalelkan forloop dari kode berikut. Bagaimana cara melakukannya?

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


Jawaban:


10
#!/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

Selalu gunakan pekerja saat menelurkan jumlah proses berparameter dan batasi jumlah maksimum pekerja yang bisa muncul .

xargs -n | while read adalah cara sederhana daftar iterasi dalam batch.

  • seq membuat daftar angka dari 1 hingga N.
  • xargs -n memecah daftar itu menjadi N / pekerja + 1 batch.
    • misal N = 100 pekerja = 10 akan menghasilkan 10 baris hingga 11 angka dari 1 hingga 100.
  • while read i membaca setiap baris angka.
  • work ${i} &hanya memanggil workfungsi dengan ${i}sejumlah angka.

Untuk debug saya telah menambahkan kode debug komentar. Cukup ganti echodengan versi debug dan kode antara # --dengan versi debug-nya dan Anda dapat melihat cara kerjanya pada batch. Batalkan komentar set -xuntuk hasil debug yang lebih terperinci yang mungkin ingin Anda redirect ke file.

Jalankan saja versi debug dengan parameter berbeda untuk melihat bagaimana operasinya:

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

Penafian: Kode ini tidak menyinkronkan minnilai antara proses pekerja. Mendapatkan nilai minimum bukanlah latihan yang mengerikan. Ini mungkin akan dilakukan:

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

Atau cukup tambahkan yang sama ke skrip itu sendiri:

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

Bisakah Anda menjelaskan kodenya? Tidak jelas bagi saya bagaimana Anda menggunakan utas pekerja di sini.
RIchard Williams

@prasenjit Selesai. Saya harap itu membantu.
nicerobot

8

Menggunakan GNU Parallel:

#!/bin/bash

N=$1
n=$2

arr=($(
# Generate all combinations of 1..n and 1..N
parallel -k --tag /path/to/a.out {1} {2} '|' bc :::: <(seq $N) <(seq $n) |
  perl -ane 'BEGIN{$min=1e30} $last||=$F[0]; if($F[0] != $last) {print $min,"\n";$min=1e30;$last=$F[0]} $min = $F[2]<$min ? $F[2] : $min; END {print $min,"\n"}'
))
echo ${arr[*]}

Ini akan berjalan /path/to/a.outpada masing-masing cpu. Outputnya akan seperti:

1 1 19269
1 2 6158
1 3 2794
1 4 25104
2 1 13160
2 2 32683
2 3 12535
2 4 15197
3 1 8228
3 2 7673
3 3 8428
3 4 24463

Script perl melihat kolom pertama dan menemukan minimum di kolom ke-3 yang memiliki kolom pertama yang sama.

Anda dapat menginstal GNU Parallel hanya dengan:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

Tonton video intro untuk mempelajari lebih lanjut: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


Tautan di paragraf terakhir Anda terhubung ke halaman pencarian Facebook yang memberi tahu pengunjung bahwa ia telah memenangkan hadiah eksklusif (iklan atau penipuan). Tidak ada video. Anda harus menghapusnya.
Marco
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.