9个优化代码运行效率的方法你知道几个?

1.1 示例代码


  1. for (i = 0; i < n; i++) {  
  2.   int nni = n*i;  
  3.   for (j = 0; j < n; j++)  
  4.     a[ni + j] = b[j];  

1.2 分析代码

代码如上所示,外循环每执行一次,我们要进行一次乘法计算。i = 0,ni = 0;i = 1,ni = n;i = 2,ni = 2n。因此,我们可以把乘法换成加法,以n为步长,这样就减小了外循环的代码量。

1.3 改进代码


  1. int ni = 0 
  2. for (i = 0; i < n; i++) {  
  3.   for (j = 0; j < n; j++)  
  4.     a[ni + j] = b[j];  
  5.   ni += n;         //乘法改加法  

计算机中乘法指令要比加法指令慢得多。

2. 提取代码中的公共部分

2.1 示例代码

想象一下,我们有一个图像,我们把图像表示为二维数组,数组元素代表像素点。我们想要得到给定像素的东、南、西、北四个邻居的总和。并求他们的平均值或他们的和。代码如下所示。


  1. up =    val[(i-1)*n + j  ];  
  2. down =  val[(i+1)*n + j  ];  
  3. left =  val[i*n     + j-1];  
  4. right = val[i*n     + j+1];  
  5. sum = up + down + left + right; 

2.2 分析代码

将以上代码编译后得到汇编代码如下所示,注意下3,4,5行,有三个乘以n的乘法运算。我们把上面的up和down展开后会发现四格表达式中都有i*n + j。因此,可以提取出公共部分,再通过加减运算分别得出up、down等的值。


  1. leaq   1(%rsi), %rax  # i+1  
  2. leaq   -1(%rsi), %r8  # i-1  
  3. imulq  %rcx, %rsi     # i*n  
  4. imulq  %rcx, %rax     # (i+1)*n  
  5. imulq  %rcx, %r8      # (i-1)*n  
  6. addq   %rdx, %rsi     # i*n+j  
  7. addq   %rdx, %rax     # (i+1)*n+j  
  8. addq   %rdx, %r8      # (i-1)*n+j 

2.3 改进代码


  1. long iinj = i*n + j;  
  2. up =    val[inj – n];  
  3. down =  val[inj + n];  
  4. left =  val[inj – 1];  
  5. right = val[inj + 1];  
  6. sum = up + down + left + right; 

改进后的代码的汇编如下所示。编译后只有一个乘法。减少了6个时钟周期(一个乘法周期大约为3个时钟周期)。


  1. imulq %rcx, %rsi  # i*n  
  2. addq %rdx, %rsi  # i*n+j  
  3. movq %rsi, %rax  # i*n+j  
  4. subq %rcx, %rax  # i*n+j-n  
  5. leaq (%rsi,%rcx), %rcx # i*n+j+n 
  6. … 

对于GCC编译器来说,编译器可以根据不同的优化等级,有不同的优化方式,会自动完成以上的优化操作。下面我们介绍下,那些必须是我们要手动优化的。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章