【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
2、 在编写的代码的时候,我们强调需要对循环首先进行循环内部的计算,然后进行循环外面的计算。在此,我们可以进行下面一个测试:
void loop_analyse()
{
int m = GetTickCount();
int inner = 0;
int outer = 0;
for(outer = 0; outer < 1000; outer ++)
{
for (inner = 0; inner < 1000; inner ++)
{
a[outer][inner] = inner;
}
}
printf("%d\n", GetTickCount() - m);
m = 0;
for(inner = 0; inner < 1000; inner ++)
{
for (outer = 0; outer < 1000; outer ++)
{
data[outer][inner] = inner;
}
}
printf("%d\n", GetTickCount() - m);
}
我们在VC6.0上面的测试结果是31、64。原因就是我们的数据在内存中间是按照先内存,然后再按照外层的顺序排列的。如果在计算的时候,我们首先使用了内部的数据,那么在cpu cache命中率上就会很高。相反,如果按照outer进行数据的遍历的话,那么就需要进行数据的不停跳转,在cpu cache上面也需要不停地进行刷新。在一旦cpu的cache命中率下降,就会重新将数据从内存加载到cpu的cache上面。等到循环得到一定的积累之后,就会在时间的运算上面发生很大的变化。两者之间的运行效率差异就会变得非常明显。
3、尽可能在循环的时候只运行本层的数据,我们可以做下面一个测试用例。
int data1[10000000] = {0,1};
int data2[10000000] = {0,1};
void loop_layer_test()
{
int m = GetTickCount();
int outer = 0;
int inner = 0;
for(outer = 0; outer < 10000000; outer ++)
{
data1[outer] = outer;
data2[outer] = outer;
}
printf("%d\n", GetTickCount() - m);
m = GetTickCount();;
for(inner = 0; inner < 10000000; inner ++)
{
data1[inner] = inner;
}
for(outer = 0; outer < 10000000; outer ++)
{
data2[outer] = outer;
}
printf("%d\n", GetTickCount() - m);
}
在我的VC6.0测试的时候,两者的运行差别时间还是挺大的,有兴趣的朋友可以在自己的机器上面好好试一下,看看是不是效果显著。其实道理和上面的准则是差不多的,只不过我们这一次涉及的单层循环的东西,不过在本质上还是差别不是很大。