目录
一、什么是局部性原理
一个编写良好的计算机程序常常具有良好的局部性。也就是说。它们倾向于引用临近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。这汇总倾向性,就被称为局部性原理,这是一个持久的概念,对硬件和软件系统的设计和性能都有着极大的影响。
之所以有这个规律,很多人认为原因是:程序的指令大部分时间是顺序执行的,而且程序的集合,如数组等各种数据结构是连续存放的。
局部性原理讲的是:在一段时间内,整个程序的执行仅限于程序的某一部分,相应地,程序访问的存储空间也局限于某个内存区域。主要分为两类:
- 时间局部性:如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。
- 空间局部性:是指一旦程序访问了某个存储单元,则不久之后,其附近的存储单元也将被访问。
二、局部性原理的应用
(1)缓存结构
CPU内部的ALU(运算器)进行信息的处理,寄存器进行信息的存储,总线连接各器件,进行数据的传送。
将计算机分为数个层次:
-
寄存器 64位
-
一级缓存L1 4×64KB
-
二级缓存L2 4×256KB
-
三级缓存L3 8MB
-
内存 4GB
-
磁盘 1TB
寄存器是CPU的工作台,CPU在工作时,先从一级缓存里面找,找不到就从二级缓存里面找,依次类推。假如CPU到磁盘才有,那么这个数据就会存入内存,再存入三级缓存、二级缓存、一级缓存,最后存入寄存器,然后进行计算。所以说,可以这么看, L1是寄存器的缓存,L2是L1的缓存,依次这样下去,下面一层是上面一层的缓存。
由于各层存储之间的速度差异,CPU要高速工作,我们希望CPU需要的数据更多的就在L1里面,能够告诉获取到,不希望更多的跑到下面内存乃至磁盘里面去找,这样会花更多的时间。所以当CPU用了一个数据,计算机会遇见性的存入其他等会儿CPU可能会用到的数据到L123内存,用到的可能性越大,就能存到越接近寄存器的层次。这也才是缓存的真正意义。那么,计算机怎样才能判断一个数据接下来可能被用到?
时间局部性:如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。所以数据在寄存器被计算完成后,将会放入告诉缓存中。
空间局部性:在最近的将来将用到的信息很可能与现在正在使用的信息在空间地址上是临近的。而且基于指令顺序执行的特性,大部分的数据存储被认为是连续的。所以程序在装载入内存时,不是整体装入,而是分块(页框)装入的。
(2)循环的局部性原理
对于诸如For循环,其在执行时也遵循一定的局部性原理,我们以案例来进行讲解。
案例A:数组循环长数据引用的局部性
private static void loopArray() {
int[][] arrayC = new int[10000][10000];
long startA = System.currentTimeMillis();
int sum1 = 0;
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
sum1 += arrayC[i][j];
}
}
long endA = System.currentTimeMillis();
System.out.println(" Array行遍历结果:" + sum1 + ", 耗时:" + (endA - startA)
+ "ms");
long startB = System.currentTimeMillis();
int sum2 = 0;
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
sum2 += arrayC[j][i];
}
}
long endB = System.currentTimeMillis();
System.out.println(" Array列遍历结果:" + sum2 + ", 耗时:" + (endB - startB)
+ "ms");
}
执行结果:
Array行遍历结果:0, 耗时:79ms
Array列遍历结果:0, 耗时:1420ms
上述代码中,通过对一个10000 * 10000的二维数组进行遍历,分别从行、列两个主序维度,可以看出行遍历是列遍历效率的10倍以上。因为数组在内存中大多是顺序存放的,而多维数组主要是以行为主序进行存放,如下图所示。
对于行维度(即相当于一维数组)来说,在空间上具有良好的空间局部性原理,即a[i]总是a[i-1]后一个位置存放。
但是对于列维度来说(以列序为主序遍历),意味着每访问一个元素,就要跳过N个元素才能访问下一个,这种情况下没有良好的空间局部性。所以在遍历时出现了明显的性能差异。
案例B:排序对数组遍历的影响
本案例主要涉及局部性原理和分支预测理论,故放在性能优化相关文章中,请参照:
参考资料
https://www.zhihu.com/question/25142664/answer/60733489
《码农翻身》——刘欣