การขนานสำหรับลูป


9

ฉันต้องการขนาน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

เป็นไปได้ที่ซ้ำกันของGNU Parallel
Gilles 'หยุดความชั่วร้าย'

คำตอบ:


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

ใช้คนงานเสมอเมื่อวางไข่จำนวนกระบวนการที่กำหนดพารามิเตอร์และ จำกัด จำนวนคนงานสูงสุดที่สามารถวางไข่ได้

xargs -n | while read เป็นวิธีง่ายๆในการวนซ้ำรายการเป็นชุด

  • seq สร้างรายการหมายเลขตั้งแต่ 1 ถึง N
  • xargs -n แบ่งรายการนั้นเป็น N / คนงาน + 1 แบตช์
    • เช่น N = 100 คนงาน = 10 จะสร้าง 10 บรรทัดของจำนวนมากถึง 11 หมายเลขจาก 1 ถึง 100
  • while read i อ่านตัวเลขแต่ละบรรทัด
  • work ${i} &เพียงแค่เรียกworkฟังก์ชั่นด้วย${i}ชุดของตัวเลข

ในการแก้ไขปัญหาฉันได้เพิ่มรหัสการดีบักความคิดเห็น เพียงแค่แทนที่echoด้วยเวอร์ชันการตรวจแก้จุดบกพร่องและรหัสระหว่าง# --ด้วยรุ่นการตรวจแก้จุดบกพร่องและคุณสามารถดูวิธีการทำงานในชุด Uncomment 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

คุณอธิบายรหัสได้หรือไม่ ไม่ชัดเจนสำหรับฉันว่าคุณใช้เธรดผู้ปฏิบัติงานที่นี่ได้อย่างไร
RIchard Williams

@prasenjit เรียบร้อยแล้ว ฉันหวังว่าจะเป็นประโยชน์
nicerobot

8

ใช้ 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[*]}

สิ่งนี้จะทำงาน/path/to/a.outบนซีพียูแต่ละตัว ผลลัพธ์จะเป็นดังนี้:

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

สคริปต์ perl ดูที่คอลัมน์แรกและค้นหาค่าต่ำสุดในคอลัมน์ที่ 3 ที่มีคอลัมน์แรกเหมือนกัน

คุณสามารถติดตั้ง GNU Parallel ได้ง่ายๆโดย:

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

ดูวิดีโอแนะนำเพื่อเรียนรู้เพิ่มเติม: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


ลิงค์ในย่อหน้าสุดท้ายของคุณลิงก์ไปยังหน้าค้นหาของ Facebook ที่บอกผู้เยี่ยมชมว่าเขาได้รับรางวัลพิเศษ (โฆษณาหรือการหลอกลวง) ไม่มีวิดีโอ คุณควรลบทิ้ง
Marco
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.