存储器山是一种综合研究存储器层次结构的工具。
它反映了存储器层次结构中不同层次的带宽。也反映了具有不同的时间局部性与空间局部性的程序的性能。
通过分析存储器山的数据,还可以看出存储器系统的部分硬件参数。
简介T. Stricker于1997年在其论文中介绍了存储器山的思想,利用它对存储器系统进行全面描述,并在后来的工作中提出了术语“存储器山”。卡耐基梅隆大学教授Randal Bryant的著作《深入理解计算机系统》一书亦提出了存储器山的概念,并进行了详细分析。
理论上,每台计算机都有一个唯一的存储器山。通过运行一段测试程序,可以得到它的存储器山。了解存储器山,对应用程序的优化能起到指导作用。
下图展示了一个基于Intel Core 2 Duo 处理器的存储器山。
存储器山测试原理为了说明存储器山的测试程序的原理,首先简要介绍局部性和存储器层次结构这两个重要概念,然后介绍存储器山的定义和测试程序的原理模型1。
局部性通常,一个编写良好的(优化的)程序具有良好的局部性,主要表现在两个方面。
1)时间局部性(Temporal locality):
如果被访问过的存储器地址在较短时间内被再次访问,则程序具有良好的时间局部性。
在一定的时间内,重复访问同一个地址的次数越多,时间局部性越好。
换句话说,对同一个地址的两次访问间隔时间越短,时间局部性越好。
2)空间局部性(Spatial locality):
如果程序访问某个存储器地址后,又在较短时间内访问临近的存储器地址,则程序具有良好的空间局部性。两次访问的地址越接近,空间局部性越好。
局部性在程序中普遍存在。好的程序通常具有好的局部性,是一个普适的原理。
存储器层次结构不同类型的存储设备,其访问速率相差很大。
其基本规律为:访问速率越高的设备,单位容量的成本越高,于是越不容易做得很大。计算机系统的设计者需要在控制成本的同时,尽量提高存储器系统的速率。
受益于局部性的概念,计算机的存储器系统通常设计成一个层次结构,CPU内部的寄存器为该层次结构的最高层----它的容量最小,但速率最高。往下依次为各级cache,主存,磁盘等等。
该层次结构的运行策略是:
尽量让当前被频繁访问的存储区的内容驻留在较高层存储器,作为代价,把不常访问的存储区的内容置换到较低层存储器。同时,尽量让当前被访问的元素附近的元素也驻留在较高层存储器。一个具有良好的局部性的程序,几乎能总是访问高层的存储器,享受到最高的访问速率。
从程序员的角度来看,要尽量编写具有良好的局部性的程序,以适应层次结构,提高程序运行速率。
存储器山测试程序具有不同的时间局部性和空间局部性的程序,对存储器层次结构的利用效率是不同的。局部性较好,则能得到较快的访问速率。构造一个存储器测试程序,以不同的时间局部性和空间局部性对存储器进行访问,就能得到存储器系统在不同的局部性下的性能(即访问速率)。以控制时间局部性的变量为x轴,控制空间局部性的变量为y轴,存储器访问速率为z轴,就能得到一个三维图形,它看起来像一座有着山峰,山脊和山坡的小山,即存储器山。
通过存储器山,可以直观地看到具有不同的时间局部性和空间局部性的程序对存储器的访问速率的巨大差别。可作为程序员优化程序的参考。
更加有趣的是,通过分析存储器山的数据,还可以看出存储器系统的部分硬件参数。包括L1数据cache(简称为L1-Dcache)、L2-cache和主存(物理介质通常为SDRAM)各自的最高平均速率,L1-Dcache和L2-cache的容量,甚至L1-Dcache的行尺寸。
不过,存储器山并非万能工具。从中无法看出cache的相联度、访问延迟等参数(这些参数可以用其他测试程序间接得出,但无法从存储器山测试程序中得出)。由于连续密集访问,cache预取(Prefetching)也会被阻塞从而无法体现其效果。
存储器山测试程序的核心就是这样一个循环:
Kernel_loop(elems, stride):for (i = 0; i