C程序性能优化方法(四)

2.11一些限制因素

2.11.1寄存器溢出

  • 循环并行的好处受汇编代码描述计算的能力限制,如果我们的并行度p超过了可用寄存器数量,那么编译器会诉诸溢出,将某些临时值存放到内存中,通常是在运行时堆栈上分配空间。例如:将combine6的多累积变量模式扩展到k=10和k=20,其结果的比较如下:
    这里写图片描述
  • 现代x86-64处理器有16个寄存器,并可以使用16个YMM寄存器保存浮点数。一旦循环变量的数量超过了可用寄存器的数量,程序就必须在栈上分配一些变量。

2.11.2 分支预测和预测错误处罚

  • 现代处理器的工作远超前于当前正在执行的指令,从内存读新指令,译码指令,以确定在什么操作数上执行什么操作。只要指令遵循的是一种简单的顺序,那么这种指令流水线化就能很好的工作。当遇到分支的时候,处理器就必须猜测分支该往哪个方向走。
  • 在一个投机执行的处理器中,处理器会开始执行预测的分支目标处的指令。它避免修改任何实际的寄存器或内存位置,直到确定了实际的结果。如果预测正确,那么处理器就会“提交”投机执行的指令的结果,把他们存储到寄存器或内存,如果预测错误,处理器就必须丢掉所有投机执行的结果,在正确的位置,重新开始取指令的过程。这样做就会引起预测错误处罚,因为在产生有用的结果之前,必须重新填充流水线。
    1. 不要过分的关心可预测的分支
      实际上,现代处理器中的分支预测逻辑非常善于辨别不同的分支指令的规律的模式和长期的趋势。
    1. 书写适合用条件传送实现的代码
      分支预测只对有规律的模式可行,程序中许多测试是完全不可预测的,依赖于数据的任意特性,例如一个数是负数还是正数。
1	void minmax1(long a[], long b[], long n)
2	{
3	    long i;
4	    for(i=0; i<n; i++)
5       {   
6	        if (a[i] > b[i])
7	        {
8	            long t = a[i];
9               a[i] = b[i];
10              b[i] = t;
11          }
12      }
13  } 
在随机数据上的测试这个函数,得到的CPE大约为13.50,而对于可预测的数据,CPE为2.5~3.5,其预测错误惩罚约为20个周期。
 
1	void minmax2(loong a[], long b[], long n)
2	{
3	    long i;
4	    for(i=0; i<n; i++)
5       {
6	        long min = a[i] < b[i] ? a[i] : b[i];
7	        long max = a[i] < b[i] ? b[i] : a[i];
8	        a[i] = min;
9           b[i] = max;
10      }
11  }

对于上诉上述,无论数据是任意的,还是可预测的,CPE都大约为4.0。

2.12 本章小结

优化程序性能的基本策略:
1)高级设计。为遇到的问题选择适当的算法和数据结果。要特别警觉,避免使用那些会渐近的产生糟糕性能的算法或编码技术。
2)基本编码原则。避免限制优化的因素,这样编译器就能产生高效的代码。

  •  消除连续的函数调用。在可能时,将计算移到循环外。考虑有选择的妥协程序的模块性以获得更大的效率。
  •  消除不必要的内存引用。引入临时变量来保存中间结果。只有在最后计算出来时,擦肩过结果存放到数组或者全局变量中。
    3)低级优化。结构化代码以利用硬件功能。
  •  展开循环,降低开销,并且使得进一步的优化成为可能。
  •  通过使用多个累积变量和重新结合等技术,找到方法提高指令级并行。
  •  用功能性的风格重写条件操作,使得编译采用条件数据传送。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值