[整理]循环,代码效率

来源:互联网 发布:数控编程实例详解 编辑:程序博客网 时间:2024/06/13 13:50

今天看C编程指南里说道:

1)在多重循环中,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨循环层执行的次数。参考代码如下:

1 // 低效率:长循环在最外层
2 for (row=0; row<100; row++) 
3  { 
4     for ( col=0; col<5; col++ ) 
5     { 
6     sum = sum + a[row][col]; 
7     } 
8 } 
1 //高效率:长循环在最内层
2 for (col=0; col<5; col++ ) 
3 { 
4     for (row=0; row<100; row++) 
5     { 
6         sum = sum + a[row][col]; 
7     } 
8 } 

2)如果在循环体内,存在逻辑判断,并且循环次数很大,应将逻辑判断移到循环体的外面。参考代码如下:

1 //效率低但程序简洁
2 for (i=0; i<N; i++) 
3 { 
4      if (condition) 
5         DoSomething(); 
6      else 
7          DoOtherthing(); 
8 } 
//效率高但程序不简洁
if (condition) 
{ 
    for (i=0; i<N; i++) 
        DoSomething(); 
} 
else 
{ 
    for (i=0; i<N; i++) 
10         DoOtherthing(); 
11 } 

不是太明白如何提高效率,遂google之,CSDN社区里帖子分析的不错,

网址:http://topic.csdn.net/u/20100115/22/e073f7e8-8d22-4ef1-bc5e-1a1f20cd757a.html

         http://topic.csdn.net/t/20040923/15/3402105.html

整理记录如下:

考虑循环

1 for(i = 0; i< A; i++)
2 {
3     for(j=0; j< B ; j++)
4     {
5        foo();
6     }
7 }
8

它等价于
其总的计算时间是:

a)  i=0;  //计算1次
b)  startA:
c)   if(i<A) 
     { //计算A+1次
d)     j =0; //计算A次
e)     startB:
f)     if(j<B) 
       {//计算A*(B+1)次
g)         foo();//计算A*B次
h)         j++; //计算A*B次
i)         goto startB;//计算A*B次
       };
j)     goto startA;//计算A*B次
     }

很显然,无论如何交换顺序,g,h,i,j四个表达式最终总是需要计算相同的次数,我们可以假定他们是固定时间T

剩下的都是简单表达式,我们假定他们的计算时间是一样的t,则总的时间就是

T+(1+A+1+A+A*(B+1)) = T+2 +AB+3A

显然,如果A>B, T+2+AB+3A > T+2+AB+3B

前者是A是外层的时间,后者是B是外层的时间

注意:这种所谓的效率只有当foo()计算时间非常非常小才有意义,否则T>>AB,就没有意义了

   

     这个“跨循环层”的概念本身是说,由外层循环进入内层循环是要重新初始化循环计数器的,包括保存外层循环的计数器和加载内层循环计数器,退出内层的时候再恢复外层循环计数器。把长循环放在里面可以显著减小这些操作的数量。 但是另一方面还要注意数据结构本身的效率。

     事实上,这个例子不恰当,因为他虽然提高了编译效率,但是降低了运行时的效率。尽量保证顺序的访问数组的每一个元素。由于Windows内存的管理模式,内存是分页管理的。顺序访问数组可以基本保证页面不会来回切换,从而减少了页失效的数量,提高了程序的整体性能。这种性能的提升对于大的数组尤为明显。