RIc*_*ams 9 bash shell-script parallelism
我想并行化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
Run Code Online (Sandbox Code Playgroud)
nic*_*bot 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
Run Code Online (Sandbox Code Playgroud)
生成参数化进程数时始终使用 worker,并限制可以生成的最大 worker 数。
xargs -n | while read
是一种批量迭代列表的简单方法。
seq
创建从 1 到 N 的数字列表。xargs -n
将该列表分成 N/workers+1 个批次。
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
Run Code Online (Sandbox Code Playgroud)
免责声明:此代码不会同步min
工作进程之间的值。获得最小值并不是一个可怕的练习。这可能会:
parallel.sh 223 5 20 | tr ' ' '\n' | sort -n | head -1
Run Code Online (Sandbox Code Playgroud)
或者只是将相同的内容添加到脚本本身:
echo ${arr[*]} | tr ' ' '\n' | sort -n | head -1
Run Code Online (Sandbox Code Playgroud)
使用 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[*]}
Run Code Online (Sandbox Code Playgroud)
这将/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
Run Code Online (Sandbox Code Playgroud)
perl 脚本查看第一列并在具有相同第一列的第三列中找到最小值。
您可以简单地通过以下方式安装 GNU Parallel:
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
Run Code Online (Sandbox Code Playgroud)
观看介绍视频以了解更多信息:https : //www.youtube.com/playlist?list=PL284C9FF2488BC6D1