for 루프 병렬화


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


답변:


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 / workers + 1 배치로 나눕니다.
    • 예를 들어 N = 100 근로자 = 10은 1에서 100까지 11 개의 숫자로 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

코드를 설명 할 수 있습니까? 작업자 스레드를 어떻게 사용했는지 명확하지 않습니다.
RIchard Williams

@prasenjit 완료했습니다. 도움이 되길 바랍니다.
nicerobot 2016

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각 CPU에서 실행 됩니다. 결과는 다음과 같습니다.

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 스크립트는 첫 번째 열을보고 동일한 첫 번째 열이있는 세 번째 열에서 최소값을 찾습니다.

다음과 같이 GNU Parallel을 간단하게 설치할 수 있습니다.

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

자세한 내용은 소개 동영상을 참조하십시오. https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


마지막 단락의 링크는 방문자에게 독점 선물 (광고 또는 사기)을 당 겼음을 알리는 페이스 북보기 페이지로 연결됩니다. 동영상이 없습니다. 제거해야합니다.
Marco
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.