最基本的C语言代码级别速度优化

6年前写的东西,很不完善,但是也是过去的一个小小总结,主要针对x86平台,收藏如下:

Short to int

描叙:32位的程序中,使用int类型作循环体的索引变量比short类型具有更好的性能。循环体索引变量指 for (i=0; i<9; i++) 中的 i

背景:32位的应用程序中使用short将导致机器码变长,同时处理器需要更长的时间处理;不仅如此,大多数编译器在未优化状况下对于short类型,总是将它转换成integer后再做各种操作,操作完后再转换为short类型,增加了一些不必要的操作。

原始代码:

       unsigned short      i;

      

       for (i=0; i<N; i++)

       {

              DoSomething();

       }

优化代码:

       unsigned int          j;

      

       for (j=0; j<N; j++)

       {

              DoSomething();

       }

Pointers to register

描叙:在循环体中尽量少使用指针间接寻址,可以采取一些迂回的方法,如果可能的话,先将间接寻址的内容放在某个寄存器里面,在循环体内操作完后,再回送到指针所指的内存。

背景:间接寻址将导致至少两次以上的内存操作,这是其一。其二,由于间接寻址使得指令具有前后的依赖性(只有先获得地址才能够做取内存内容的操作),编译器的优化能力将被降低,同时对处理器中流水线的乱序,调度和指令配对也会有一定的影响

原始代码:

       int   i, j = 0, *a = &j;

      

       for (i=0; i<N; i++)

       {

           *a += i;

       }

优化代码:

       int   i, j = 0, *a = &j;

       register int      temp;

      

       temp = *a;

       for (i=0; i<N; i++)

       {

           temp += i;

       }

       *a = temp;

Move if statement out of loop core

描叙:如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面。

背景:参考下面的代码可以看到,在原始代码中要多执行N1此逻辑判断,而且循环影响了处理器中流水线原有的次序,降低了效率。

原始代码:

for (i=0; i<N; i++)

{

if (condition)

DoSomething();

else

DoOtherthing();

}

优化代码:

if (condition)

{

for (i=0; i<N; i++)

DoSomething();

}

else

{

for (i=0; i<N; i++)

DoOtherthing();

              }

Use library

描叙:如果你要实现功能在库函数里面可以找到,那么你如果还不是高高手的话,用库函数吧。

背景:库函数一般针对你的操作系统做了大量的优化,其性能是一般代码不可比拟的。比如下面的代码中,同样的内存拷贝,性能可能相差上十倍。

原始代码:

unsigned char output[N], input[N];

 

for (i = 0; i < N; i++)

{

    output[i] = input[i];

}

优化代码:

unsigned char output[N], input[N];

 

memcpy(output, input, N);

性能比较:性能将提高若干倍

Division to multiplication

描叙:将一个循环体内部的浮点除法操作,改成浮点乘法,或许有意想不到的效果。

背景:浮点数的除法比乘法要慢得多;如果是整数的乘法和除法是没有任何差异的,但是在适当地时候可以使用移位操作来提高效率,比如说将num乘以16的操作变为num<<4可以取得更好的效果,同理可应用于除法和求余,除法使用右移操作,求余使用&操作都可以取得不错的效果,至少在新版本的linux内核中已经在除法和求余操作上做了大量的改进。

原始代码:

               int i;

       double j;

             

for (i=0; i<0xffffff; i++)

               {

                     j = (double)i / 3.3;

               }

优化代码:

              int i;

       double j, k;

             

       k = (double)1.0 / 3.3;

       for (i=0; i<0xffffff; i++)

       {

              j = (double)i * k;

       }

性能比较:局部速度大约提升85

For statement

描叙:在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的

循环放在最外层,以减少CPU 跨切循环层的次数。

背景:浮点数的除法比乘法要慢得多,如果是整数的乘法和除法是没有任何差异的,但是在适当地时候可以使用移位操作来提高效率。

原始代码:

               int i;

       double j;

             

for (i=0; i<0xffffff; i++)

               {

                     j = (double)i / 3.3;

               }

优化代码:

              int i;

       double j, k;

             

       k = (double)1.0 / 3.3;

       for (i=0; i<0xffffff; i++)

       {

              j = (double)i * k;

       }

性能比较:局部速度大约提升85

Array access order

参考:高质量C++/C 编程指南》

’C’ Coding Techniques for Intel Architecture Processors

 

你可能感兴趣的:(c,优化,语言,output,linux内核,Pointers)