由于CPU的处理速度和存储器的数据存取速度之间有着巨大的差异,而且随着硬件技术的发展,这个差异还会逐步加大。CPU的设计者在CPU和存储器之间设计了高速缓存,有的分开了指令缓存(i-cache)和数据缓存(d-cache)。有的没有区分,称为统一缓存。最靠近CPU的缓存称为1级缓存L1,在L1和主存之间还有二级缓存L2,有的系统还设有3级缓存L3。这些高速缓存具有极高的数据存取速度,只需要1,2个时钟周期,接近寄存器的速度,但是由于芯片密度很高,这些资源毕竟是有限的,对于PIII Xeon的CPU,只有32KL1(16K i-cache,16K d-cache).还有512KL2(芯片外,统一缓存)。
如果我们程序对高速缓存的命中率很高,程序的执行速度会大大提高,要求程序元编写出对高速缓存友好的程序。局部性原理在计算机系统和其他一些现实案例中应用非常广范,主要是划分为:时间局部性(刚刚访问过的数据可能很快又会被访问)和空间局部性(访问的数据所在的连续地址空间内的数据很可能继续被访问)。
这里有个例子:
int test()
{
int sum=0;
int a[10][20];
for(int i=0;i<10;++i)
for(int j=0;j<20;++j)
sum +=a[i[j];
}
int test1()
{
int sum=0;
int a[10][20];
for(int i=0;i<20;++i)
for(int j=0;j<10;++j)
sum +=a[j][i];
}
测试结果是:test1显著慢于test要慢5倍以上,随着数组维数的增大差距扩大更厉害。
在上面2个例子中,for循环中的i,j,还有sum变量都有良好的时间局部性。
test有良好的空间局部性性,因为是按照存储顺序来访问数组的,test1就没有,访问是杂乱的。
cpu的cache组织结构是:组--->行--->块。每次填入cache时是一次性填入连续的块大小的数据。
关于高速缓存的内容比较多,上面只是个简单的示例,在矩阵乘法中,这个特性体现的更加明显。