我该怎么做才能加快这个bash脚本的速度?

时间:2016-03-31 16:16:29

标签: bash time

我的代码遍历文件并将第一列中的所有数字乘以数字。代码有效,但我认为它有点慢。它需要26.676秒(壁挂时间)才能通过一个包含2302行的文件。我使用的是2.7 GHz Intel Core i5处理器。这是代码。

#!/bin/bash

i=2
sed -n 1p data.txt > data_diff.txt #outputs the header (x  y)
while [ $i -lt 2303 ]; do
    NUM=`sed -n "$i"p  data.txt | awk '{print $1}'`
    SEC=`sed -n "$i"p  data.txt | awk '{print $2}'`
    NNUM=$(bc <<< "$NUM*0.000123981")
    echo $NNUM $SEC >> data_diff.txt
    let i=$i+1
done

3 个答案:

答案 0 :(得分:5)

老实说,你可以获得的最大加速来自于使用可以完成整个任务的单一语言。这主要是因为你的脚本为每个行调用了5个额外的进程,并且调用额外的进程很慢,但是bash中的文本处理实际上并没有那么好地优化。

我推荐awk,因为你有它可用:

awk '{ print $1*0.000123981, $2 }'

我确信你可以改进这一点,跳过标题行并不加修改地打印出来。

你也可以使用Perl,Python,C,Fortran和许多其他语言来做这类事情,尽管这种简单的计算不太可能有太大的区别。

答案 1 :(得分:4)

您的脚本运行4603个单独的sed进程,4602个单独的awk进程和2301个单独的bc进程。如果echo不是内置的,那么它也会运行2301 echo个进程。启动进程的开销相对较大。没有那么大,你通常会注意到它,但你运行超过11000个短流程。壁挂时间的消耗似乎并不合理。

此外,您运行的每个sed都会重新处理整个输入文件,只选择一行。这非常低效。

解决方案是减少正在运行的进程数,尤其是只对整个输入文件执行一次运行。一个相当简单的方法是转换为awk脚本,可能使用bash包装器。这可能看起来像这样:

#!/bin/bash

awk '
NR==1    { print; next }
NR>=2303 { exit }
         { print $1 * 0.000123981, $2 }
' data.txt > data_diff.txt

请注意,以NR>=2303开头的行在到达第2303行时会人为地停止处理输入文件,就像原始脚本一样;你可以完全省略脚本的那一行,让它只是处理所有的行,无论有多少行。

请注意,它使用awk的内置FP算法而不是运行bc。如果你真的需要bc的任意精度算术,那么我相信你可以弄清楚如何修改脚本来实现它。

答案 2 :(得分:3)

作为如何加速rebootInstances脚本的示例(并不意味着这是正确的解决方案)

bash

现在,每个数据行只需要对#!/bin/bash { IFS= read -r header echo "$header" # You can drop the third name "rest" if your input file # only has two columns. while read -r num sec rest; do nnum=$( bc <<< "$num * 0.000123981" ) echo "$nnum $sec" done } < data.txt > data_diff.txt 进行一次额外调用,因为bc不执行浮点运算。正确的答案是使用单个调用来编程可以执行浮点运算,正如David Z所指出的那样。