并发与运行时调度(2) - cpu local cache

在系统运行中,我们常常忽视cpu local cache miss/hit带来的性能差异,因此,有必要了解cpu local cache的工作机制,为高性能程序的开发提供理论指导。

存储体系结构

通常来说,现代计算机存储结构基本可分为如下等级:

register -> local cache -> memory -> disk storage,其中local cache可能分为L1/L2/L3等多个级别。

参考如下链接可以对各存储器的访问延时有一个直观的印象:

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

从中可以发现,访问主存耗时是访问cpu local cache耗时的10倍以上,因此基于时间和空间局部性假设设置cpu local cache能够有效提高程序性能。

local cache加载机制

local cache分为多个cache line,每个line的存储部分的大小为32~64byte,cache line是local cache与memory交换数据的基本单位。

每个cache line包括三个部分:

Valid:当前缓存是否有效
Tag:对应的内存地址
Block:缓存数据部分

local cache与memory映射关系

全关联映射

主存任意一块可以映射到Cache的任意一块
优点:空间利用率高、命中率高
缺点:访问存储器时,每次都要全部查找,速度低,基本不使用

直接映射

主存中的一块只能映射到Cache的一个特定的块中
优点:映射简单,访问速度快
缺点:替换频繁,命中率低

组相连映射

主存根据Cache大小划分多个区,每个区划分成多个组,每个组内划分多个块
Cache划分成多个组,每个组内划分多个块
主存的每个区与Cache直接映射,组内采用全映射方式

缓存一致性协议

既然使用了cache,就存在缓存不一致的问题,local cache通过一套缓存一致性协议保证cache间的一致性,该协议被称为MESI协议。

事实上,MESI是cache line中数据的四种状态,分别如下:

状态描述
M(Modified)这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。
E(Exclusive)这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。
S(Shared)这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。
I(Invalid)这行数据无效。

 

 

 

 

 

 

既然有状态,自然就有状态转移,状态转移过程如下:

当前状态

事件

行为

下一个状态

I(Invalid)

Local Read

如果其他Cache没有这份数据,本Cache从该内存中取数据,Cache line状态变成E;

如果其他Cache有这份数据,且状态为M,则将数据更新到内存,本Cache再从内存中取数据,两个Cache的Cache line状态都变成S;

如果其他Cache有这份数据,且状态为S或者E,本Cache从内存中取数据,这些Cache的Cache line状态都变成S。

E/S

Local Write

从内存中取数据,在Cache中修改,状态变成M;如果其他Cache有这份数据,切状态为M,则要先将数据更新到内存;

如果其他Cache有这份数据,则其他Cache的Cache line状态变成1

M

Remote Read

既然是invalid,别的核的操作与它无关

I

Remote Write

既然是invalid,别的核的操作与它无关

I

E(Exclusive)

Local Read

从Cache中取数据,状态不变

E

Local Write

修改Cache的数据,状态为M

M

Remote Read

数据和其他核共用,状态变成了S

S

Remote Write

数据被修改,本Cache line不能再使用,状态变成I

I

S(Shared)

Local Read

从Cache中取数据,状态不变

S

Local Write

修改Cache中的数据,状态变成M,其他核共享的Cache line状态变成I

M

Remote Read

状态不变

S

Remote Write

数据被修改,本Cache line不能再使用,状态变成I

I

M(Modified)

Local Read

从Cache中取数据,状态不变

M

Local Write

修改Cache中的数据,状态不变

M

Remote Read

这行数据被写到内存中,使其他核能使用到最新的数据,状态变成S

S

Remote Write

这行数据被写到内存中,使其他核能使用到最新的数据,由于其它核会修改这行数据,状态变成I

I

 

状态转移图如下:

false sharing

由前述所知,local cache是以cache line为单位进行加载的,当两个不同cpu core的线程更新的两个不同变量恰好位于同一cache line时,由于MESI协议的作用,线程将频繁地从L3甚至memory更新cache line,导致大量的cache miss,这种现象被称为false sharing,即由于cache line加载机制导致local cache miss的现象。

false sharing如下图所示:

volatile关键字和cas实现机制

volatile解决的可见性问题由前述分析可知基于MESI实现。

cas首先修改local cache并尝试invalidate该cache line,由MESI仲裁后,成功者完成操作,失败者接受该结果,invalidate自身cache line后重新尝试进行操作。

在高性能程序开发中的实际应用

典型应用如disruptor中采用缓存行填充(padding)机制,杜绝false sharing,提升性能。

JDK1.8中ConcurrentHashMap的long类型封装类

参考文章:

https://www.jianshu.com/p/061a5d66ea20

http://www.voidcn.com/article/p-hkyurame-zt.html

https://blog.csdn.net/qq_27680317/article/details/78486220

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值