CPU Cache 基础解析

文末含分享内容视频链接

CPU Cache 基础

最近看了一些 CPU 缓存相关的东西,在这里做一下记录。

Wiki 词条:CPU cache - Wikipedia

一些基本概念

CPU 缓存出现的原因

  1. 主存一般是 DRAM,CPU 速度比主存快很多倍,没有缓存存在时 CPU 性能很大程度取决于读取存储数据的能力
  2. 比 DRAM 快的存储介质是存在的,比如作为 CPU 高速缓存的 SRAM,只是很贵,做很大的 SRAM 不经济
  3. CPU 访问数据存在时间局部性和空间局部性,所以可以将 CPU 需要频繁访问的少量热数据放在速度快但很贵的 SRAM 中,既能大幅度改善 CPU 性能也不会让成本提升太多

Cache Line

CPU 每次访问数据时先在缓存中查找一次,找不到则去主存找,访问完数据后会将数据存入缓存,以备后用。这就产生了一个问题,CPU 在访问某个地址的时候如何知道目标数据是在缓存中存在?如何知道缓存的数据是否还有效没被修改?不能为每个存入缓存的字节都打标记,所以 CPU 缓存会划分为固定大小的 Block 称为 Cache Line,作为存取数据的最小单位。大小都为 2 的整数幂,比如 16 字节,256 字节等。这样一个 cache line 这一整块内存能通过一个标记来记录是否在内存中,是否还有效,是否被修改等。一次存取一块数据也能充分利用总线带宽以及 CPU 访问的空间局部性。

Cache Write Policy

Cache 不光是在读取数据时有用,目前大部分 CPU 在写入数据时也会先写 Cache。一方面是因为新存数据很可能会被再次使用,新写数据先写 Cache 能提高缓存命中率;另一方面 CPU 写 Cache 速度更快,从而写完之后 CPU 可以去干别的事情,能提高性能。

CPU 写数据如果 Cache 命中了,则为了保持 Cache 和主存一致有两种策略。如果 CPU 写 Cache 每次都要更新主存,则称为 Write-Through ,因为每次写 Cache 都伴随主存更新所以性能差,实际使用的也少;写 Cache 之后并不立即写主存而是等待一段时间能积累一些改动后再更新主存的策略称为 Write-Back ,性能更好但为了保证写入的数据不丢使机制更加复杂。采用 Write Back 方式被修改的内存在从 Cache 移出(比如 Cache 不够需要腾点空间)时,如果被修改的 Cache Line 还未写入主存需要在被移出 Cache 时更新主存,为了能分辨出哪些 Cache 是被修改过哪些没有,又需要增加一个新的标志位在 Cache Line 中去标识。

CPU 写数据如果 Cache 未命中,则只能直接去更新主存。但更新完主存后又有两个选择,将刚修改的数据存入 Cache 还是不存。每次直接修改完主存都将主存被修改数据所在 Cache Line 存入 Cache 叫做 Write-Allocate 。需要注意的是 Cache 存取的最小单位是 Cache Line。即使 CPU 只写一个字节,也需要将被修改字节所在附近 Cache Line 大小的一块内存完整的读入 Cache。如果 CPU 写主存的数据超过一个 Cache Line 大小,则不用再读主存原来内容,直接将新修改数据写入 Cache。相当于完全覆盖主存之前的数据。

写数据时除了需要考虑上述写 Cache 策略外,还需要保持各 CPU Cache 之间的一致性。比如一个 CPU 要向某个内存地址写数据,它需要通知其它所有 CPU 自己要写这个地址,如果其它 CPU 的 Cache Line 内有缓存这个地址的话,需要将这个 Cache Line 设置为 Invalidate。这样写数据的那个 CPU 就能安全的写数据了。下一次其它 CPU 要读这个内存地址时,发现这个 Cache Line 是 Invalidate 状态,所以需要重新从内存做加载,即发生一次 Communication Miss。这种 Miss 不是 Cache 不够大,也不是 Cache 冲突,而是因为其它 CPU 写同一个 Cache Line 里数据导致了 Cache Miss。缓存一致性维护需要专门文章来写。

SMP 和 NUMA

SMP 词条:Symmetric multiprocessing - Wikipedia
NUMA 词条:Non-uniform memory access - Wikipedia

简单说 SMP 就是一组 CPU 会通过一条总线共享机器内的内存、IO 等资源。因为所有东西都是共享的,所以扩展性受限。

NUMA 则是将机器内 CPU 分为若干组,每个组内都有独立的内存,IO资源,组与组之间不相互共享内存和 IO 等资源,组之间通过专门的互联模块连接。总体上扩展性更强。

本文主要以 SMP 系统为例。CPU 以及 Cache,Memory 的关系如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H2wxDx3V-1586935954154)(http://lc-kaK4q1Br.cn-n1.lcfile.com/9688c18e01749b0f4d93/cpu%201.jpg)]

CPU 缓存结构

Direct Mapped Cache

最简单的缓存结构就是 Direct Mapped 结构。如下图所示,每个 Cache Line 由基本的 Valid 标志位,Tag 以及 Data 组成。当访问一个内存地址时,根据内存地址用 Hash 函数处理得到目标地址所在 Cache Line 的 Index。根据 Index 在 Cache 中找到对应 Cache Line 的 Data 数据,再从 Data 中根据内存地址的偏移量读取所需数据。因为 Hash 函数是固定的,所以每一个内存地址在缓存上对应固定的一块 Cache Line。所以是 Direct Mapped。

实际中为了性能 hash 函数都非常简单,就是从内存地址读取固定的几个 bit 数据作为 Cache Line 的 Index。拿下图为例,Cache Line 大小为 4 字节,一共 32 bit 是图中的 Data 字段。4 字节一共需要 2 bit 用于寻址,所以看到 32 bit 的地址中,0 1 两个 bit 作为 Offset。2 ~ 11 bit 作为 Cache Line 的 Index 一共 1024 个,12 ~ 31 bit 作为 tag 用于区分映射到相同 Cache Line 的不同内存 block。比如现在要读取的地址是 0x1124200F,先从地址中取 2 ~ 11 bit 得到 0x03 表示目标 Cache Line 的 Index 是 3,之后从地址中读 12 ~ 31 bit 作为 tag 是 0x11242。拿这个 Tag 跟 Index 为 3 的 Cache Line 的 Tag 做比较看是否一致,一致则表示当前 Cache Line 中包含目标地址,不一致则表示当前 Cache Line 中没有目标地址。因为 Cache 比内存小很多,所以可能出现多个不在同一 Cache Line 的内存地址被映射到同一个 Cache Line 的情况,所以需要用 Tag 做区分。最后,如果目标地址确实在 Cache Line,且 Cache Line 的 Valid 为 true,则读取 0x1124200F 地址的 0 ~ 1 bit,即找目标数据在 Cache Line 内的 Offset,得到 0x03 表示读取当前 Cache Line 中最后一个字节的数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PeR6GMdg-1586935954156)(http://lc-kaK4q1Br.cn-n1.lcfile.com/81f96f5f750d870b7039/cpu%202.jpg)]

上图的 Cache 是 1024 X 4 字节 一共 4 KB。但由于 Tag 和 Valid 的存在,缓存实际占用的空间还会更大。

替换策略

因为 Direct Mapped 方式下,每个内存在 Cache 中有固定的映射位置,所以新访问的数据要被存入 Cache 时,根据数据所在内存地址计算出 Index 发现该 Index 下已经存在有效的 Cache Line,需要将这个已存在的有效 Cache Line 从 Cache 中移出。如果采用 Write-Back 策略,移出时需要判断这个数据是否有被修改,被修改了需要更新主存。

Write-Back 策略在前面有介绍,即写数据时只写缓存就立即返回,但标记缓存为 Dirty,之后在某个时间再将 Dirty 的缓存写入主存。

Two-way Set Associative Cache

我们希望缓存越大越好,越大的缓存经常意味着更快的执行速度。对于 Direct Mapped Cache 结构,增大缓存就是增加 Index 数量,相当于是对上面表进行纵向扩展。但除了纵向扩展之外,还可以横向扩展来增加 Cache 大小,这就是 Two-way Set Associative Cache。

基本就是如下图所示,图上省略了 Tag 和 Valid 等标识每个 cell 就是一个 Cache Line,与 Direct Mapped Cache 不同点在于,Two-way Set Associative Cache 里每个 Index 对应了两个 Cache Line,每个 Cache Line 有自己的 Tag。同一个 index 下的两个 cache line 组成 Set。在访问内存时,先根据内存地址找到目标地址所在 Set 的 index,之后并发的去验证 Set 下的两个 Cache Line 的 Tag,验证目标地址是否在 Cache Line 内,在的话就读取数据,不在则去读主存。

这里并发的验证两个 Cache Line 的 Tag 是由硬件来保证,硬件电路结构会更加复杂但查询效率与 Direct Mapped Cache 一致。

Set 内的两个 Cache Line 是具有相同 Index 的两个不同 Cache Line。上图来自 Is Parallel Programming Hard, And, If S

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CPU缓存代理是一种位于CPU内部的硬件组件,用于优化计算机处理数据的性能。 在计算机体系结构中,CPU缓存代理是位于CPU和内存之间的缓存层次结构中的一个组件。它的作用是在CPU执行指令时提供快速访问数据。CPU缓存代理通过将最常用的数据存储在靠近CPU的高速缓存内,可以减少内存访问的延迟时间。 CPU缓存代理主要包括三级缓存:L1缓存、L2缓存和L3缓存。L1缓存位于CPU内部,与CPU核心紧密连接,速度最快,容量最小。L2缓存位于L1缓存之后,速度稍慢,容量较大。L3缓存位于CPU芯片上,容量最大,速度相对较慢。 CPU缓存代理的工作原理是通过缓存替换算法和缓存一致性协议来管理缓存中的数据。缓存替换算法决定了何时将新数据加载缓存中,以及何时将旧数据替换出去。缓存一致性协议则保证了多核CPU中各个核心之间访问共享内存的一致性。 CPU缓存代理的存在可以显著提升计算机的性能。由于缓存可以更快速地访问数据,CPU不需要每次都从内存中读取数据,而是直接从缓存中读取,从而减少了内存的访问延迟。此外,CPU缓存代理还可以减少对内存总线的压力,提高数据传输效率。 总之,CPU缓存代理是一个重要的硬件组件,可以提升计算机处理数据的性能。它通过在CPU和内存之间提供高速缓存来减少内存访问的延迟,并通过缓存替换算法和缓存一致性协议来管理缓存中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值