文章插图
那么,Cache的命中率会成为程序运行性能非常关键的事,所以,了解上面的这些东西,会有利于我们知道在什么情况下有可以导致缓存的失效 。
对于 N-Way 关联我们取个例子,并多说一些细节(因为后面会用到),Intel 大多数处理器的L1 Cache都是32KB,8-Way 组相联,Cache Line 是64 Bytes 。于是,
- 32KB的可以分成,32KB / 64 = 512 条 Cache Line 。
- 因为有8 Way,于是会每一Way 有 512 / 8 = 64 条 Cache Line 。
- 于是每一路就有 64 x 64 = 4096 Byts 的内存 。
- Tag :每条 Cache Line 前都会有一个独立分配的 24 bits来存的 tag,其就是内存地址的前24bits
- Index :内存地址后续的6个bits则是在这一Way的是Cache Line 索引,2^6 = 64 刚好可以索引64条Cache Line
- Offset :再往后的6bits用于表示在Cache Line 里的偏移量
文章插图
(图片来自《 Cache: a place for concealment and safekeeping 》)
这意味着:
- L1 Cache 可映射 36bits 的内存地址,一共 2^36 = 64GB的内存
- 因为只要头24bits相同就会被映射到同一个Way中,所以,每4096个地址会放在一Way中 。
- 当CPU要访问一个内存的时候,通过这个内存的前24bits 和中间的6bits可以直接定位相应的Cache Line 。
缓存的一致性对于主流的CPU来说,缓存的写操作基本上是两种策略(参看本站《 缓存更新的套路 》),
- 一种是Write Back,写操作只要在cache上,然后再flush到内存上 。
- 一种是Write Through,写操作同时写到cache和内存上 。
好了,现在问题来了,如果有一个数据 x 在 CPU 第0核的缓存上被更新了,那么其它CPU核上对于这个数据 x 的值也要被更新,这就是缓存一致性的问题 。(当然,对于我们上层的程序我们不用关心CPU多个核的缓存是怎么同步的,这对上层都是透明的)
一般来说,在CPU硬件上,会有两种方法来解决这个问题 。
- Directory 协议 。这种方法的典型实现是要设计一个集中式控制器,它是主存储器控制器的一部分 。其中有一个目录存储在主存储器中,其中包含有关各种本地缓存内容的全局状态信息 。当单个CPU Cache 发出读写请求时,这个集中式控制器会检查并发出必要的命令,以在主存和CPU Cache之间或在CPU Cache自身之间进行数据同步和传输 。
- Snoopy 协议 。这种协议更像是一种数据通知的总线型的技术 。CPU Cache通过这个协议可以识别其它Cache上的数据状态 。如果有数据共享的话,可以通过广播机制将共享数据的状态通知给其它CPU Cache 。这个协议要求每个CPU Cache 都可以 “窥探” 数据事件的通知并做出相应的反应 。
文章插图
因为Directory协议是一个中心式的,会有性能瓶颈,而且会增加整体设计的复杂度 。而Snoopy协议更像是微服务+消息通讯,所以,现在基本都是使用Snoopy的总线的设计 。
这里,我想多写一些细节,因为这种微观的东西,不自然就就会更分布式系统相关联,在分布式系统中我们一般用Paxos/Raft这样的分布式一致性的算法 。而在CPU的微观世界里,则不必使用这样的算法,原因是因为CPU的多个核的硬件不必考虑网络会断会延迟的问题 。所以,CPU的多核心缓存间的同步的核心就是要管理好数据的状态就好了 。
推荐阅读
- 每个程序员都必须知道的8种通用数据结构
- 服务器又崩溃了?看看专业的程序员怎么解决
- 交换机与路由器相比的五点优势
- 祁门红茶十大名牌,祁门红茶的前世与今生
- 家居住宅财富运势:如何寻找财位与如何催财
- 碧螺春功效,碧螺春的功效与作用
- 砖茶功效作用,砖茶的作用与功效
- 皇菊功效,金丝皇菊的功效与禁忌
- 百香果茶,苹果茶的功效与作用
- 寻茶之旅:一片单株古树茶与茶人的千年之约