香山访存和缓存一致性优化听课笔记
1、基本概念与区别
缓存一致性=cache cocherence
访存一致性=memory consistency
访存一致性是程序行为和硬件行为的比较结果,一般考虑多核场景下的访存一致性。即程序序列和内存序列(全局序)的执行结果是否一致。
最严格的访存一致性要求是SO,sequential order。本地load的结果是全局同地址的最近store结果。其他全局序要求也严格。
次严格的访存一致性要求是TSO。本地load的结果要么是全局同地址的最近store结果,要么是本地程序的同地址最近store结果。
TSO意味着程序员需要在软件上做出内存一致性保护措施,比如在多进程编程时检查自旋锁,否则就无法保护load的结果正确。
而TSO的硬件收益则很大,允许硬件把store请求以queue存储,无论是阻塞式的或是非阻塞式的queue(区别在于entry项数),总是能尽可能地消除访存引起的流水线阻塞,让后续的指令能够继续执行。
代价是,数据相关指令的发射和提交仍然要检查sq的相关性并阻塞,控制相关指令的提交可能会回滚sq。sq和后续访存流水本身具有深度,在执行store的时候也可以作一些适配cache延迟/总线延迟的优化。
sq不一定需要以fifo来实现。
riscv提出的内存一致性模型RVWMO更加宽松,只需要全局序存在且满足公理支撑的形式化定义即可。RVWMO允许更多的乱序,不仅仅局限于S-L关系的乱序。
这种做法使得sq可以合并写请求(降低写功耗和写延迟),这种优化也必然是建立在non-fifo的queue上的。load在bypass先前结果时,本来无法检查store结果的时效(因fifo结构),但是现在可以做到bypass多个结果其中之一。
同时,RVWMO对fence指令的实现和编程提出了更高要求。
缓存一致性旨在处理cache数据的有效性。它是以任一单核(master)视角去检查的。
若要保持cache数据的有效性,不仅要维护d-cache本身的结构,维护自身访存带来的冲突(若访存取指不合并为一个master),还要关注其他master对cache的影响。
在单master看来,互连网络cache模型等效于原子访存模型。
原子访存模型指,每次内存仅开放接口给一个master使用,必然能保证缓存一致性。
2、缓存一致性的实现
访存一致性的实现如上所述,与ISA强相关。具体将在fence指令实现和香山访存结构研究笔记中继续讨论。
缓存一致性的实现基本上对软件透明,需要由硬件完成。
为了描述其他master对自身cache有效性的影响,最基本的一致性模型VI模型,其状态转移条件包括如下条件Own-put,Other-get;Own-get
put=写回(释放),get=索要。
前两者使得valid变为invalid,这很容易理解。在valid状态下own-get会自选,都不影响cache的有效性(对其他master的有效性)。在valid状态下own-put会打破自身dcache和other dcache的一致性,所以只能该为invalid。这同时引出一个必然的推论,对同一地址而言(cacheline),valid状态或invalid在全局中只能由一家master持有,否则就无法区分当前地址的最新更新位置。而valid的变化要么通知邻居,要么被邻居索要。被邻居索要的场合,master发出response,并且把自身状态变为invalid。
所以,状态转移条件使得后者使得invalid变为valid,并且执行data-response给,master。值得注意的是,Own-put,Other-get是同时发生的等价操作。
在VI模型下,invalid和valid的唯一选择有待深入补充,正常来说,valid状态下的cacheline是被master所独享的。
但上述论述已经推出了VI模型的硬件结构,每个cacheline都需要维护自身的VI状态,相应寄存器称为MSHR,miss history handing register,也有其他用途。
为了通知邻居和向邻居查询缓存状态,互联总线是必须的。为了避免master之间的通信,master的private cache可以总是和内存保持一致。那么master之间的一致性查询就转化为master和内存的数据一致性比较。
在VI模型下,cache读写权限是统一的。但实际上,other在读的时候,master自身也可以共享读权限,这是可优化点之一。
所以一种对VI模型的改进称为MSI模型。M=modified,S=share,I=invalid。
share是仅予以cache读权限的状态,此时cacheline被多个master加载到本地。这种细分的状态减少了master为了请求读权限而对所有邻居进行查询的开销。
MSI针对程序中常见的先read,后write操作可以继续优化。如果master从invalid状态开始执行上述操作,需要在noc上发起两次权限请求,承受两次总线延迟。但如果请求读权限时已知cacheline是clean的状态,就没必要承受第二次总线延迟,所以E(exclusive)状态被加入到MSI模型,若cacheline为clean,则master转移到E状态,由E状态转移到M状态是过程是silent,无需经过总线。
这就是MESI模型。显然,E状态和M状态一样的全局唯一的。
cacheline的clean状态由exclusive(独占)定义。cacheline变为dirty以后不可以退回到exclusive,需要在M状态完成写回,再返回到E状态或S状态。当other请求读权限,M状态或E状态返回到S状态。
上述机制保证了访存操作的(延迟 )可见性,但是没有保证访存操作的原子性(通过软件实现)、有序性(通过软件实现),仍然有可能产生死锁,需要其他机制配合。
一致性协议需要实现的特性是,事务串行化(对同一个地址),写传播。
snoop是一致性协议的重要概念。非原子模型的一致性协议,可以基于snooping或基于目录(directory)来传递一致性消息。
snooping机制把cache controller和cache合并,cache之间通过shared bus共享消息,对总线带宽要求高。所有cache管理自身的状态机。共享消息的机制,要么是write update,要么是write invalidate。
directory机制把所有把cache controller和cache分离,如前所述。cache之间通过统一的directory共享消息。拥有directory的cache,会通过directory查询cacheline的master,然后点对点的请求权限。
cacheline当前的主人可能并不是其M状态的拥有者,所以需要继续转发权限请求,owner获得权限,写回,把权限共享给请求者(若是读取),并且发送一个invalidate A(若是写操作)。
转发请求的流程属于浪费,但也省略了广播的开销,属于用增加串行事务气泡的方式来避免总线的全部占用和接收,忽略了与自身无关的snoop=invalidate/update,避免了snoop方式对总线带宽的消耗。
而且,转发请求的流程至多一次,无需反复查询(指发起请求只需一次,实际经过多跳网络可能仍然需要多跳延时)。当网络规模扩大,这种方式节约总线带宽优势更加明显。
事务中的一对节点为local node、home node。对此无感知的节点为remote node。
3、Tilelink