存储器层次结构(读书笔记)

December 10th, 2013 by JasonLe's Tech Leave a reply »

最近在看存储器层次结构,之前知道各级存储器为了弥补速度上的巨大差距,开发出了cache来提高命中率,加快取指运算的速度。

这对我们编写代码来说有非常重要的影响,因为许多程序具有局部性,包括时间局部性与空间局部性。

在现在CPU中,往往具有多级cache L1 L2 L3 ,在i7处理器中,L1 的数据cache 指令cache为每个核私有,L2 cache连接L1上面的两个cache,L3为所有核共享。

cache与主存连接的方式有多种:直接映射高速缓存,组相连映射高速缓存。

直接映射高速缓存就是每组只有一行的高速缓存。

QQ Photo20131210214514

第二个则是每组有多行高速缓存,通过标记位来识别每个组中哪行是要寻找的cache。

Unnamed QQ Screenshot20131210220106

这两种方式都是用高位地址标记特定行,中间标记特定组,地位标记块偏移量。高速缓存利用的是地址位的中间位作为缓存的索引,所以这样做相对于使用地址高位作为索引的好处是,主存相邻的块总是映射到不同的高速缓存行。这一点又是我们可以利用在程序性能提高上的原理所在。

比如一个13位地址,0-1 块偏移量,2-4组索引,5-12缓存标记
比如引用地址0x0E34 换算成二进制就是 0111000 110 100 对照2路高速缓存寻找组索引 标记位,偏移量 如果cache没有数据,那就从主存中获取,并保留一份给cache。

根绝上述的这个,我们要编写高速缓存友好的代码。
1.让最常见的情况运行的更快。
2.在每个循环内部缓存不命中数量最小。

最主要的就是对局部变量反复引用,步长为一的模式多多使用。

int sumarrayrows(int a[M][M])
{
    int i,j,sum=0;

    for(i=0;i<M;i++)
      for(j=0;j<M;j++)
         sum+=a[i][j];
         //sum += a[j][i];
    return sum;
}

因为数组在内存中以行排列的,所以如果没有命中,他会把内存后面的几个载入cache,如果以列寻址,cache将每次都无法命中,产生抖动。