“ 本文的参考文章是2022年HOT 34上Intel Rob Blakenship关于CXL缓存一致性的一篇介绍。”
冯诺依曼说,数据应该存在这里,这里变成了存储器;
冯诺依曼说,数据应该在这里被计算,这里变成了CPU;
冯诺依曼没有说,CPU太快而存储太慢。CPU没有办法只能把一部分数据留在身边,慢慢地就成了各级缓存。每个CPU都留了一部分数据在身边,就得维护这些数据和内存的一致性。
(有时间可以再聊聊拜占庭将军问题和共识机制,又要分布式的好,还有集中式的一致性,有点类似。)
1缓存/caching
缓存就是临时把数据存在靠近数据要消费的地方。
放数据的地方有不同的级别,不同级别的延时和带宽都不一样,因此就会有预取。更详细的硬件预取器的文章可以参考以下几篇拙作。
预取就是在数据真正需求之前把数据取回来。既然可以预取就说明数据具有两个性质:
空间局部性:一般来说需求的数据在之前的数据附近
时间局部性:一般来说需求的数据总是之前用过的
现代CPU一般都会有多级的缓存,并且他们都可以保持缓存一致。
L1:空间最小,延时最低,带宽最高
L3:空间更大,延时更高,带宽较低,并且支持多个数据需求来源
那么如何保证缓存一致性呢?
首先需要在更新缓存之前,确保使得其他人拥有的该缓存无效。
这可以通过软件的手段,也可以通过硬件的手段。CXL使用硬件一致性。
CXL和CPU的缓存一致性协议相同,都是基于以下几个状态:
Modified:该数据只被缓存到一个cache中,可读可写,但是还没有更新到内存中;
Exclusive:该数据只被缓存到一个cache中,可读可写,数据与内存同步;
Shared:该数据被缓存到多个cache中,可读,数据与内存同步;
Invalid:该数据没有被缓存;
2缓存的家 Home
内存以64Byte为单位分好,这一份就是一个cacheline。
系统通过物理地址把这些单位都安排好,然后交给Home Agent来管理,有且仅有一个。
也就是说一个cacheline,只有一个家,例如在两路系统中,要么是CPU0,要么是CPU1。
比如说,你要读一个cacheline,你会首先在本地的cache里找,如果没有的话,你就会去找它的家。也就是Home Agent会去问其他的CPU是不是有这个缓存。
如果你要写一个cacheline,你也需要找它的家,获取写权限,然后让Home Agent告诉其他的CPU放弃该cacheline,当然在放弃之前,需要把最新的数据回写给Home Agent。
Home Agent怎么问其他CPU,或者修改cacheline的状态呢?这个就是Snoop消息。
3CXL 缓存协议
为支持设备访问系统主存,cxl.cache有15个读写操作指令。
CXL3.0开始,每一个端口可以最多支持16个缓存设备,而在此之前,只能支持一个。
在CPU和CXL设备之间,有两个通讯方向,一个是H2D,一个是D2H。
顾名思义,host和device 的两个方向。而每个方向分成三个通道/channel,分别为请求,响应和数据通道。
4举个栗子
Device首先发一个RdShared:Read Cacheline Share State。设备获取了某个cacheline并且获得S-state,然后host返回Go-S。表示Home Agent同意了这个请求,并且该设备的cacheline变成了Shared state。
看看就好,不能动手。
这里的peer cache可以是各种邻居:
CXL的邻居设备;
本CPU中的cache;
远端CPU中的cache;
而这里的内存控制器也可以是各种内存:
本CPU的传统DDR;
远端CPU的传统DDR;
邻居CXL设备上的CXL.mem;
CXL的15个request,就不再一一解释,露个脸:
Reads: RdShared, RdCurr, RdOwn, RdAny
Read-0: RdownNoData, CLFlush, CacheFlushed
Writes: DirtyEvict, CleanEvict, CleanEvictNoData
Streaming Writes: ItoMWr, WrCur, WOWrInv, WrInv(F)
5内存池化和共享
池化内存和CXL switch是CXL增加的内容,这使得从host到内存的专属分配成为共享内存的一种方式。
CXL3增加了多个host共享内存的支持,利用HDM-DB。
先写到这里,缓存一致性的具体流程不再详细解释,细心一点的朋友可以多找几个例子,按照图示和步骤对照一下。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !