局部性原理详解


参考文章

学过计算机底层原理、了解过很多架构设计或者是做过优化的同学,

应该很熟悉局部性原理。


即便是非计算机行业的人,在做各种调优、提效时也不得不考虑到局部性,

只不过他们不常用局部性一词。


如果抽象程度再高一些,

甚至可以说地球、生命、万事万物都是局部性的产物,

因为这些都是宇宙中熵分布布局局部的熵低导致的,

如果宇宙中处处熵一致,有的只有一篇混沌。


所以什么是局部性

这是一个常用的计算机术语,

是指

处理器在访问某些数据时

短时间内存在重复访问,

某些数据或者位置访问的概率极大,

大多数时间只访问局部的数据。


基于局部性原理,

计算机处理器在设计时做了各种优化,

比如现代CPU的多级Cache分支预测……


有良好局部性的程序比局部性差的程序运行得更快。

虽然局部性一词源于计算机设计,

但在当今分布式系统互联网技术里也不乏局部性,

比如像用redis这种memcache来减轻后端的压力,

CDN做素材分发减少带宽占用率……


平均分布

局部性的本质是什么?

其实就是概率的不均等

这个宇宙中,

很多东西都不是平均分布的,

平均分布是概率论中几何分布的一种特殊形式,

非常简单,

但世界就是没这么简单。


高斯分布

我们更长听到的发布叫做高斯发布

同时也被称为正态分布

因为它就是正常状态下的概率发布

起概率图如下,但这个也不是今天要说的。


99.7% of the data are within 3 standard deviations of the mean

95% within 2 standard deviations

68% within 1 standard deviation

99.7%的数据都在平均值加减3个标准差之内

95%的数据都在平均值加减2个标准差之内

68%的数据都在平均值加减1个标准差之内

μ(mu)

σ(sigma)


泊松分布

其实有很多情况,很多事物有很强的头部集中现象

可以用概率论中的泊松分布来刻画,

这就是局部性概率学中的刻画形式。

上面分别是泊松分布的示意图和概率计算公式,

λ \lambda λ

表示单位时间(或单位面积)内随机事件的平均发生次数,

e e e表示自然常数2.71828..

k表示事件发生的次数。

可以参考的文章有:

泊松分布的简单介绍

泊松分布的公式详解


要注意

刻画局部性

λ \lambda λ表示不命中高频数据的频度,

λ \lambda λ越小,头部集中现象越明显

局部性分类

局部性有两种基本的分类,

时间局部性

空间局部性

按Wikipedia的资料,可以分为以下五类,其实有些就是时间局部性空间局部性的特殊情况。


时间局部性(Temporal locality):

如果某个信息这次被访问,那它有可能在不久的未来被多次访问。

时间局部性是空间局部性访问地址一样时的一种特殊情况。

这种情况下,可以把常用的数据加cache来优化访存


空间局部性(Spatial locality):

如果某个位置的信息被访问,那和它相邻的信息也很有可能被访问到

这个也很好理解,我们大部分情况下代码都是顺序执行,数据也是顺序访问的。


内存局部性(Memory locality):

访问内存时,大概率会访问连续的块,而不是单一的内存地址,

其实就是空间局部性在内存上的体现

目前计算机设计中,都是以块/页为单位管理调度存储,其实就是在利用空间局部性来优化性能。


分支局部性(Branch locality)

这个又被称为顺序局部性,计算机中大部分指令是顺序执行,顺序执行和非顺序执行的比例大致是5:1,

即便有if这种选择分支,其实大多数情况下某个分支都是被大概率选中的,

于是就有了CPU的分支预测优化


等距局部性(Equidistant locality)

等距局部性是指如果某个位置被访问,那和它相邻等距离的连续地址极有可能会被访问到,它位于空间局部性和分支局部性之间。

举个例子,

比如多个相同格式的数据数组,你只取其中每个数据的一部分字段,那么他们可能在内存中地址距离是等距的,

这个可以通过简单的线性预测就预测是未来访问的位置。


实际应用

计算机领域关于局部性非常多的利用,

有很多你每天都会用到,

但可能并没有察觉,

另外一些可能离你会稍微远一些,

接下来我们举几个例子

来深入了解下局部性的应用


计算机存储层级结构

上图来自极客时间徐文浩的《深入浅出计算机组成原理》,

我们以目前常见的普通家用电脑为例 ,

分别说下

上图各级存储的大小访问速度

数据来源于

https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html

从最快的L1 Cache到最慢的HDD,

其两者的访存时间差距

达到了6个数量级,

即便是和内存比较,也有几百倍的差距。


举个例子,

如果CPU在运算时

直接从内存中读取指令和数据,

执行一条指令0.3ns,

然后从内存读下一条指令,等120ns,

这样CPU 99%计算时间都会被浪费掉。

但就是因为有局部性的存在,

每一层都只有少部分数据会被频繁访问,

我们可以把这部分数据从底层存储挪到高层存储

可以降低大部分的数据读取时间。


可能有些人好奇,

为什么不把L1缓存做的大点,

像内存那么大,直接替代掉内存,不是性能更好吗?

虽然是这样,但是L1 Cache单位价格要比内存单位的价格贵好多(大概差200倍),

有兴趣可以了解下DRAMSRAM


我们可以通过编写高速缓存友好的代码逻辑来提升我们的代码性能,

有两个基本方法。


1、让最常见的情况运行的快,

程序大部分的运行

实际都花在少数核心函数上,

而这些函数把大部分时间都花在少量循环上,

把注意力放在这些代码上。

2、让每个循环内缓存不命中率最小。

比如尽量不要列遍历二维数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值