![for 루프 병렬화](https://linux55.com/image/19599/for%20%EB%A3%A8%ED%94%84%20%EB%B3%91%EB%A0%AC%ED%99%94.png)
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
목록을 일괄적으로 반복하는 간단한 방법입니다.
seq
1부터 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
답변2
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[*]}
이는 /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