Song song một vòng lặp for


9

Tôi muốn song song các forvòng lặp của đoạn mã sau. làm như thế nào?

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


Câu trả lời:


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

Luôn sử dụng công nhân khi sinh ra một số lượng quy trình được tham số hóa và giới hạn số lượng công nhân tối đa có thể sinh sản .

xargs -n | while read là một phương tiện đơn giản để lặp lại danh sách theo đợt.

  • seq tạo một danh sách các số từ 1 đến N.
  • xargs -n chia danh sách đó thành N / worker + 1 đợt.
    • ví dụ: N = 100 worker = 10 sẽ tạo ra 10 dòng có tối đa 11 số từ 1 đến 100.
  • while read i đọc từng dòng số.
  • work ${i} &chỉ cần gọi workhàm với số ${i}lô.

Để gỡ lỗi tôi đã thêm mã gỡ lỗi nhận xét. Chỉ cần thay thế echobằng phiên bản gỡ lỗi và mã giữa # --với phiên bản gỡ lỗi của nó và bạn có thể thấy nó hoạt động như thế nào trên các lô. Uncomment set -xcho một đầu ra gỡ lỗi chi tiết hơn mà bạn có thể muốn chuyển hướng đến một tập tin.

Chỉ cần chạy phiên bản gỡ lỗi với các tham số khác nhau để xem cách nó hoạt động:

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

Tuyên bố miễn trừ trách nhiệm: Mã này không đồng bộ hóa mingiá trị giữa các quy trình worker. Lấy giá trị tối thiểu không phải là một bài tập kinh khủng. Điều này có thể sẽ làm:

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

Hoặc chỉ cần thêm tương tự vào chính kịch bản:

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

Bạn có thể giải thích mã? Tôi không rõ bạn đã sử dụng các luồng công nhân ở đây như thế nào.
RIchard Williams

@prasenjit Xong. Tôi hy vọng điều đó hữu ích.
nicerobot

8

Sử dụng song song GNU:

#!/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[*]}

Điều này sẽ chạy /path/to/a.outtrên mỗi cpu. Đầu ra sẽ như sau:

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

Kịch bản perl nhìn vào cột đầu tiên và tìm mức tối thiểu trong cột thứ 3 có cùng cột đầu tiên.

Bạn có thể cài đặt GNU Parallel đơn giản bằng cách:

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

Xem các video giới thiệu để tìm hiểu thêm: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


Liên kết trong đoạn cuối của bạn liên kết đến một trang tìm kiếm trên facebook cho khách truy cập biết rằng anh ta đã giành được một món quà độc quyền (quảng cáo hoặc lừa đảo). Không có video. Bạn nên loại bỏ nó.
Marco
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.