咱们描述许多提升代码性能的技术。理想的状况是编译器可以接受咱们编写的任何代码并产生尽量高效的、具备指定行为的机器级程序现代编译器采用了复杂的分析和优化方式并且变得愈来愈好,然而即便是最好的编译器也受到了妨碍优化因素的阻碍。程序员必须编写容易优化的代码,帮助编译器。html
两个指针可能指向一个内存位置称为 内存别名使用git
void twiddle1(long *xp,long *yp){ *xp += *yp; *xp += *yp; }
当考虑指针 xp 和 yp 指向相同内存地址时,该函数可能产生二义性,及xp值翻了4倍程序员
当函数修改全局变量等 反作用 时,可能会妨碍优化。
那么算法
long counter = 0; long func1opt(){ long t = 4 * counter + 6; counter += 4; return t; } 经过内联替换函数调用 显然优于 long func1in(){ long t = counter++; t += counter++; t += counter++; t += counter++; return t; }
void psum2(float a[],float p[],long n) { long i; p[0] = a[0]; for(i = 1;i < n-1;i += 2){ float mid_val =p[i-1] + a[i]; p[i] = mid_val; p[i+1] = mid_val + a[i+1]; } if(i < n) p[i] = p[i-1] + a[i]; }
当使用for循环迭代计算前置和。每次调用函数都会执行创建栈帧和恢复栈帧,这一段代码的耗时是一个定值S。随着循环次数n的变化,总的耗时T=S + n*L,其中L为for循环的单位循环执行时间,在本书中又称做每元素周期数CPE。数组
上述代码的运行时间近似于 368+6.0n ,所以psum2的CPE为6.0。安全
void combine4(vec_ptr v,data_t *dest){ long i; long length = vec_length(v); data_t *data = get_vec_start(v); data_t acc = IDENT; for(i = 0;i < length;i++){ acc = acc + data[i]; } *dest = acc; } 经过将循环中的累计结果放在临时的局部变量中,能够消除每次循环迭代没必要要的内存读写
若是计算循环索引和测试循环条件的循环开销部分所占比重过大,这时就能够考虑使用一种被称做"循环展开"的方式来优化代码。所谓循环展开就是经过在每次迭代中执行更多的数据操做来减少循环开销的影响。其基本思想是设法把操做对象线性化,而且在一次迭代中访问线性数据中的一小组而非单独的某个。这样获得的程序将执行更少的迭代次数,因而循环开销就被有效地下降了。数据结构
循环展开技术的好处在于它能减少循环开销的影响。但它也不是没有缺点的,天下没有免费的午饭!首先,循环展开增长了生成的目标代码的数量,这很容易理解,由于循环体在源代码级别就已经变得庞大。读者能够试想它们被翻译成目标代码时的状况。为了验证这一点,读者可使用Visual C++来对比使用循环展开先后循环体的汇编代码的长度,验证结果将代表循环展开对目标代码的长度的确有很大的影响。固然,在咱们所举的例子中,循环展开所要付出的代价都是比较小的。固然这并不能归纳其余全部的状况,所以这个空间换时间的折中最优位置还须要针对具体问题来作具体的分析。 使用循环展开时一方面要考虑实际待处理数组的长度,并由此选择一个较好的展开度;另外一方面要综合考虑这个展开度对时空开销比例的影响,在尽可能不会使目标代码空间消耗激增的前提下得到最高的时间收益。另外,也可让编译器为咱们完成这些工做。一般,编译器能够很容易地执行循环展开,但这须要设定其优化级别足够高,因此程序员也能够选择让编译器来完成这个工做。固然,咱们曾经提醒过读者,在开发阶段并不适合将优化级别设置得太高,所以若是你但愿让编译器执行循环展开,那么最好等到软件开发完成以后。并发
for(i=0;i<limit;i+=2){ acc = (acc OP data[i]) OP data[i+1]; } 经过减小循环次数,减小关键路径上的操做数量。
for(i=0;i<limit;i+=2){ acc = acc OP (data[i] OP data[i+1]); } 经过从新结合变换,提升程序并行性。
想要大幅提升整个系统的速度,必须提升整个系统很大一部分的速度。取决于这个部分有多么重要和速度提升了多少。函数
博客园连接:http://www.cnblogs.com/LeeX1997/性能
经过本周的再次学习,让我对于如何编写高效代码有了进一步理解。
更重要的是,对于 高级语言-编译器-处理器 之间的关系更明确了。