今天看C编程指南里说道:
1)在多重循环中,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨循环层执行的次数。参考代码如下:
2 for (row = 0 ; row < 100; row + + )
3 {
4 for ( col = 0 ; col < 5; col + + )
5 {
6 sum = sum + a[row][col];
7 }
8 }
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)如果在循环体内,存在逻辑判断,并且循环次数很大,应将逻辑判断移到循环体的外面。参考代码如下:
2 for (i = 0 ; i < N; i + + )
3 {
4 if (condition)
5 DoSomething();
6 else
7 DoOtherthing();
8 }
2 if (condition)
3 {
4 for (i = 0 ; i < N; i + + )
5 DoSomething();
6 }
7 else
8 {
9 for (i = 0 ; i < N; i + + )
10 DoOtherthing();
11 }
不是太明白如何提高效率,遂google之,CSDN社区里帖子分析的不错,
http://topic.csdn.net/t/20040923/15/3402105.html
整理记录如下:
考虑循环
2 {
3 for (j = 0 ; j < B ; j + + )
4 {
5 foo();
6 }
7 }
8
它等价于
其总的计算时间是:
b) startA :
c) if (i < A)
d) j = 0 ; // 计算A次
e) startB :
f) if (j < B)
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内存的管理模式,内存是分页管理的。顺序访问数组可以基本保证页面不会来回切换,从而减少了页失效的数量,提高了程序的整体性能。这种性能的提升对于大的数组尤为明显。