企业宣传网站公司,免费制作个人简历的网站,网页的开发流程,工业信息化部网站备案系统CPU 缓存机制 1. CPU Cache 与 MMU1.1 MMU 是什么#xff1f;TLB 又是什么#xff1f;他们是怎么工作的#xff1f;2.2 简述 Cache 与 MMU 的协作关系#xff1f;2.3 简述 Cache 与 MMU 的协作工作流程#xff1f; 2. CPU 多层次缓存2.1 什么是 CPU 的多层次缓存结构… CPU 缓存机制 1. CPU Cache 与 MMU1.1 MMU 是什么TLB 又是什么他们是怎么工作的2.2 简述 Cache 与 MMU 的协作关系2.3 简述 Cache 与 MMU 的协作工作流程 2. CPU 多层次缓存2.1 什么是 CPU 的多层次缓存结构2.2 为什么 CPU 缓存要分级2.3 L1、L2 和 L3 缓存在设计上有何不同2.4 为什么 L1 cache 采用分离缓存的方式而 L2、L3 采用统一缓存的形式 3. CPU 缓存的工作原理3.1 缓存组织结构映射方式有哪几种类型3.2 Set-Associative Cache组相联缓存的结构是什么样的3.3 简述 Set-Associative Cache组相联缓存的工作流程3.4 Cache 体系结构有哪几种3.5 Cache 替换策略有哪几种3.6 详细描述 CPU 从发出内存请求到得到返回过程中Cache 和内存执行的完整流程3.7 写操作中 Cache 分配策略有哪些最常用的策略是什么3.8 读操作中 Cache 分配策略有哪些最常用的策略是什么 4. 缓存一致性Cache Coherence4.1 缓存一致性Cache Coherence问题是怎么发生的如何解决4.2 MESI 协议是什么他是如何保证缓存一致性的 众所周知CPU是计算机的大脑负责处理指令并执行任务。但是在我们日常的计算和程序执行中有一个不可或缺的部分那就是CPU缓存。在当今的计算机架构中CPU缓存起到了至关重要的作用尤其是对于程序性能的优化。为了更好地理解它我们需要深入了解它的设计和工作原理。
1. CPU Cache 与 MMU
1.1 MMU 是什么TLB 又是什么他们是怎么工作的 MMUMemory Management Unit和TLBTranslation Lookaside Buffer在现代计算机体系结构中起到关键作用它们与内存访问和虚拟内存管理有关。以下是关于它们工作原理和流程的详细描述。 MMU (Memory Management Unit) MMU是计算机中的一个硬件单元负责将虚拟地址转换为物理地址。在有虚拟内存的系统中程序并不直接与物理内存进行通信而是通过虚拟地址。这种方式为每个程序提供了一个看似连续的地址空间而实际上这些地址可能分散在物理内存和磁盘页面文件或交换区中。 MMU 工作原理 当程序尝试访问虚拟内存地址时这个地址首先传递给MMU。MMU使用页表来查找与虚拟地址相关联的物理地址。页表可能非常大不可能完全存储在快速存取的硬件内所以通常存储在主内存中。MMU转换虚拟地址为物理地址并将其发送到物理内存以进行访问。 TLB (Translation Lookaside Buffer) 由于频繁地从页表中查找地址转换是非常耗时的因此TLB被引入作为一个小型的、快速的缓存。用于存储最近的虚拟到物理的地址转换。 TLB 工作原理 当虚拟地址需要被转换时MMU首先检查TLB。如果TLB中存在所需的转换称为TLB命中那么从TLB中直接获取物理地址跳过完整的页表查找。如果TLB没有所需的转换称为TLB缺失MMU必须在页表中进行查找。一旦找到了转换它通常会被添加到TLB中替换一个旧的条目。在某些情况下所需的页面可能不在物理内存中导致页面错误。这时操作系统需要从磁盘中加载所需的页面并更新页表和TLB。 MMU 与 TLB 工作流程 CPU生成虚拟地址并发送给MMU。MMU检查TLB以查找地址转换。如果TLB命中MMU直接得到物理地址。如果TLB缺失MMU查找页表。更新TLB如果发生了TLB缺失。如果发生页面错误操作系统介入从磁盘加载页面并再次尝试地址转换。 2.2 简述 Cache 与 MMU 的协作关系 Cache 和 MMUMemory Management Unit是两个主要的硬件组件它们在现代计算机体系结构中起到关键作用。尽管它们有不同的功能和目的但它们之间有一定的关系特别是在处理存储访问和优化性能时。 功能与目的 Cache主要目的是提供一个比主存更快速的存储层次从而缩短 CPU 和主存之间的延迟差距。它存储了最近或最常访问的数据和指令以便快速获取。MMU它的主要功能是虚拟内存管理即将虚拟地址转换为物理地址。这样程序可以认为它们在一个连续的地址空间中运行而不用关心数据或指令实际存储的物理位置。 关系 当 CPU 请求某个地址的数据或指令时这通常是一个虚拟地址。在访问 cache 之前这个地址需要被 MMU 转换为物理地址。对于某些 cache 结构例如 VIPTVirtually Indexed, Physically Tagged部分虚拟地址用于索引 cache而转换为的物理地址用于标记匹配。在发生 cache 缺失的情况下MMU 的地址转换过程变得尤为重要因为现在需要访问主存而主存访问基于物理地址。 互动 TLBTranslation Lookaside Buffer是 MMU 的一个组件它是一个特殊的、小型的 cache用于缓存最近使用的地址转换。这样对于连续的访问不需要每次都在主页表中查找地址转换。 当 cache 和 MMU 连续工作时如上所述首先是 TLB 的查找为了地址转换然后是 cache 的查找。如果两者都缺失那么将需要从主存中获取数据并可能需要完整的页表查找。 总之Cache 和 MMU 都是为了优化性能而存在的。缓存旨在减少存储访问的延迟而 MMU 则允许更灵活和高效的内存管理和保护。 2.3 简述 Cache 与 MMU 的协作工作流程 Cache 和 MMU 基本上都是一起使用的会同时开启或同时关闭。因为 MMU 页表中的 entry 属性控制着内存的权限和 cache 缓存的策略。对于物理高速缓存与虚拟高速缓存Cache 与 MMU 协同工作流程会有所不同。 物理高速缓存的工作流程(图源 知乎黑客与摄影师) CPU 在访问 DDR 的时候用的地址是虚拟地址需要经由 MMU 转换为物理地址。MMU 会先查询 TLB 获取物理地址若 TLB 未命中则需要访问页表来查询物理地址。通过物理地址查询 Cache若 Cache 未命中则CPU 需要从 DDR 中获取数据。 虚拟高速缓存的工作流程(图源 知乎黑客与摄影师) CPU 在寻址时先把虚拟地址发送到 Cache若命中则直接返回。若 Cache 未命中则经由 MMU 转换为物理地址去查询 DDR。 2. CPU 多层次缓存 如下图所示为常见的 CPU 多级缓存架构示意图图源 知乎努力的码农
2.1 什么是 CPU 的多层次缓存结构 CPU的多层次缓存结构是为了平衡存取速度和大小的关系提供了多个层级的缓存。随着制程技术的进步CPU的运行速度远远超过了主存RAM的速度导致CPU经常等待数据。为了缓解这种情况CPU设计者引入了多层次的缓存每一层的速度和大小都是一个折衷。下面是常见的多层次缓存结构 L1缓存 (Level 1): 通常嵌入在CPU核心内部。速度最快但容量相对较小通常在几十KB到几百KB之间。有时分为指令缓存用于存储即将执行的指令和数据缓存。 L2缓存 (Level 2): 速度比L1缓存慢但容量更大通常在几百KB到几MB之间。可以嵌入在CPU核心内或者与一组核心共享。 L3缓存 (Level 3): 比L2缓存慢但容量更大可以达到几十MB。通常是所有CPU核心共享的位于CPU芯片上但不嵌入在核心内。 L4缓存 (Level 4) 和更高层缓存: 不是所有系统都有这些高级的缓存。通常位于特定的高性能计算系统或集成了eDRAM的CPU中。其容量可以非常大但访问速度相对较慢。 随着层次的提高每一层缓存的访问时间逐渐增加但容量也随之增大。目的是捕获不同的局部性L1缓存捕获时间局部性即最近用过的数据可能很快再次被使用L2和L3缓存捕获空间局部性即如果某个地址被访问那么其附近的地址可能也会很快被访问。 2.2 为什么 CPU 缓存要分级 缓存的分级设计主要是为了解决存储器的速度与容量之间的矛盾。这是因为在存储技术中通常速度快的存储器成本较高并且容量较小而速度慢的存储器成本较低且容量较大。以下是将缓存分级的主要原因 成本与性能的平衡 最接近CPU的缓存级别如L1由于其高速特性通常是最昂贵的。为了使整个系统的成本效益最大化设计者会选择较小但非常快速的L1缓存然后使用更大、稍慢、但成本效益更高的L2和L3缓存来补充。 减少访问延迟 L1缓存设计得非常接近CPU从而实现非常低的数据访问延迟。如果L1未命中L2和可能的L3会作为后备这些缓存的访问时间虽然较长但仍然比直接从主内存中获取数据要快得多。 有效利用空间与带宽 缓存分级意味着较高级别的缓存可以更有效地利用其存储空间因为它们主要缓存下一级缓存中的热点数据。这也意味着高级缓存更有可能命中从而减少对主内存的访问并节省带宽。 工作负载隔离 不同的应用和工作负载可能会对不同级别的缓存产生不同的压力。通过分级可以确保一些核心或线程不会完全填满缓存从而使其他核心或线程饿死。 增加并发性 通过有多级缓存同时发出的多个数据请求可以在不同的缓存级别上被同时服务这增加了处理器的并发数据访问能力。 节省能量 访问L1缓存通常比访问L2或L3缓存更省电。因此如果数据可以在L1中找到则可以避免更多的能源消耗。 总的来说缓存的分级是为了在速度、成本、功耗和容量之间找到最佳的平衡。这种平衡允许系统达到接近最速存储器性能的速度同时保持较大的缓存大小和合理的成本。 2.3 L1、L2 和 L3 缓存在设计上有何不同 L1 采用分离缓存Harvard 架构 在这种架构下指令和数据被存储在物理上分离的两个缓存中。这意味着有一个专门的指令缓存 (I-Cache) 和一个专门的数据缓存 (D-Cache)。优势可以同时访问指令和数据这有助于提高处理速度。 并且可以独立地优化每个缓存来适应其使用模式。劣势需要更多的硅面积实现物理上的分离。 如果其中一个缓存使用得不多但另一个缓存面临压力则不能动态地重新分配空间。 L2/L3 采用统一缓存Von Neumann 架构 在这种架构下指令和数据共享同一个物理缓存。优势缓存的总体使用更为灵活因为它可以动态地为指令和数据分配空间。 设计和实现上更简单需要的硅面积可能更少。劣势不能同时从缓存中取指令和访问数据这可能降低处理速度。 指令和数据争用相同的缓存空间可能导致更频繁的缓存失效。 2.4 为什么 L1 cache 采用分离缓存的方式而 L2、L3 采用统一缓存的形式 缓存的设计受到多种因素的影响 访问速度 L1缓存因为它位于CPU非常近的位置L1缓存的设计目标是最大限度地减少延迟。分离的指令和数据缓存可以允许同时进行指令取址和数据访问从而加快执行速度。L2/L3缓存相对于L1来说L2和L3的延迟较高但它们主要是为了提供更大的容量从而减少对主内存的访问。因为延迟已经存在所以设计上可以稍微复杂一些合并指令和数据在同一缓存中。 面积和复杂性 L1缓存分离的指令和数据缓存意味着每个缓存可以被优化为其特定的访问模式。此外由于L1缓存的大小相对较小所以分离不会造成太大的面积开销。L2/L3缓存这些缓存级别通常比L1缓存大得多。将指令和数据合并在一个统一的缓存中可以简化设计并节省硅面积。 局部性 L1缓存分离缓存可以更好地利用指令和数据的局部性因为它们不会相互驱逐彼此的条目。L2/L3缓存在这些级别数据和指令的访问模式变得更加混合所以合并在一个统一的缓存中可以更好地利用总体的局部性。 功耗 L1缓存由于L1缓存频繁地被访问所以它的功耗是一个重要考虑因素。分离的设计可以减少不必要的访问例如当CPU只需要数据时只访问数据缓存而不是同时访问指令缓存。 总的来说L1、L2 和 L3 缓存之间的设计差异是由于它们在 CPU 存储器层次结构中的角色和目标所导致的。L1 缓存的主要目标是速度而 L2 和 L3 缓存的主要目标是容量和减少对主内存的访问。 3. CPU 缓存的工作原理
3.1 缓存组织结构映射方式有哪几种类型 缓存组织结构一般有以下三种类型: Direct-mapped Cache (直接映射缓存): 在这种结构中每个主存中的块只能映射到缓存的一个特定位置。这是通过将主存块地址除以缓存的块数量来决定的。由于这种直接映射方法查找速度非常快。但是这种方法可能会导致许多缓存冲突尤其是如果两个经常被访问的主存块被映射到同一个缓存位置时。 Fully Associative Cache (全相联缓存): 在全相联缓存中主存中的任何块都可以放在缓存的任何位置。当CPU查找一个块时它会在缓存的每个位置上进行查找通常使用并行搜索。这消除了由于冲突导致的缓存未命中但是查找速度可能较慢并且实现上更加复杂和昂贵。 Set-Associative Cache (组相联缓存): 这是前两种类型的折中。缓存被分为几个集合每个集合包含一定数量的缓存行。一个主存块可以映射到一个特定的集合但在那个集合中它可以放在任何缓存行中。例如在 2-way set-associative 缓存中每个集合有两个缓存行。查找时只需要在指定的集合中搜索这大大减少了搜索的时间和复杂性。 这三种类型都有其利弊选择哪种类型取决于实际应用的需求。例如高性能的处理器可能会使用 2-way 或 4-way 组相联缓存作为其 L1 缓存因为这提供了良好的折中方案而 L2 或 L3 缓存可能有更高的相联度因为它们更大并且查找速度可以稍微慢一些。 3.2 Set-Associative Cache组相联缓存的结构是什么样的 Set-associative组相联缓存的基本结构如下图所示 组Set 在 set-associative 缓存中缓存被分成了多个集合。每个集合都包含一个或多个缓存行。 当 CPU 尝试从缓存中查找数据时它会根据该数据的地址来确定要查找哪个集合。 缓存块/行Cache Block/Line 缓存块是缓存的最小单元。 一个缓存块的常见大小为 32 字节、64 字节或 128 字节与系统内存块的大小是一致的。 当主存储器的一部分数据被加载到缓存中时它会被加载到一个缓存行中。 每个缓存行不仅包含数据还包含该数据在主存储器中的地址的一部分通常称为标签。 路Way 或 Slot 指 set-associative 缓存中每个集合的缓存行数。 例如上图中如果一个缓存是 4-way set-associative 的那么每个集合有 4 个缓存行或槽位。 这意味着当数据从主存加载到这个集合时它可以放在 4 个可能的缓存行中的任何一个。 缓存地址Cache address CPU 访问 cache 时的地址编码 包含 3 个部分偏移量Block Offset域、索引Set Index域和标记Tag域。 块内偏移Block Offset 这部分地址用于在缓存块内部选择特定的字节数据。这部分的位数决定了一个缓存块或称为缓存行的大小。例如如果一个缓存块是32字节那么你需要5位来表示这32字节中的每一个字节因为2^5 32。 组索引Set Index 主存地址的某一部分被用作索引以确定数据应该放在缓存的哪个集合中。这部分的位数取决于缓存中组的数量。例如如果缓存有128组那么需要7位来索引这些组因为2^7 128。 标签Tag 这部分包含了地址的其余部分并存储在标签存储器中。当检索缓存时这部分与标签存储器中的标签进行比较以确定所请求的数据是否在缓存中。 标签存储器Tag memory 对于每个数据块都有一个与之对应的条目在标签存储器中。 它用于存储每个缓存块中数据的源地址信息。当 CPU 查找缓存时它会检查标签存储器来确定缓存中是否包含所需的数据。 每个条目通常包含 3 部分标签Tag、有效位Valid Bit、脏位/读写位Dirty Bit or R/W Bit 有效位Valid Bit 这个位表示缓存中的一个特定块是否包含有效数据。当进行缓存清除或初始化时这个位通常被设置为0。 修改位/脏位Dirty Bit 这个位表示数据是否被修改。如果脏位被设置意味着该缓存行的数据与主内存中的数据不匹配并且在某个时刻需要将其写回主内存。 3.3 简述 Set-Associative Cache组相联缓存的工作流程 组相联缓存尝试在直接映射的确定性和全相联的灵活性之间找到一个平衡。通过允许每个内存块映射到多个但不是全部的缓存行它提供了更高的命中率而不牺牲太多的复杂性或成本。以下是组相联缓存的工作流程 地址解码: 当 CPU 生成一个地址以检索某些数据时这个地址被分解成三部分标签Tag、组索引Set Index和块内偏移Block Offset。 选择缓存组: 使用组索引Set Index来选择对应的缓存组。 标签比较: 在选定的缓存组中每个缓存行的标签都与请求地址的标签进行比较。这是并行进行的因为我们需要快速地确定数据是否存在于任何给定的行中。 数据检索/存储: 命中如果任何行的标签与请求地址的标签匹配并且有效位表示该行是有效的那么这就是一个缓存命中。从该行中的块内偏移位置检索数据。未命中如果没有行的标签与请求地址匹配或者匹配的行无效那么这是一个缓存未命中。处理器将从主内存中获取数据可能会替换掉缓存组中的一个旧行。 替换策略: 对于缓存未命中需要从主内存中加载数据到缓存。如果所选的缓存组已满我们需要选择一个缓存行来替换。常用的替换策略有最近最少使用LRU、随机替换、FIFO 等。具体使用哪种策略取决于缓存的设计。 写策略: 当 CPU 需要将数据写回到一个地址时缓存需要决定是立即写回到主内存写回策略还是仅当该行被替换时才写回写通过策略。考虑到写分配策略和不写分配策略的选择可以决定在写操作未命中时是否加载一个新的缓存行。 3.4 Cache 体系结构有哪几种 缓存体系结构有多种设计策略主要涉及到如何处理虚拟地址和物理地址之间的映射。这些策略对于CPU的性能和复杂性都有重要影响。下面列举的三种缓存策略是最常见的 VIVT (Virtually Indexed, Virtually Tagged) 索引 使用虚拟地址进行缓存行索引。标签 使用虚拟地址进行缓存行标签比较。优点 低延迟不需要等待地址转换从虚拟地址到物理地址完成就可以进行缓存访问。简单没有必要进行地址转换。 缺点 需要处理地址空间的重叠因为不同的进程可能会有相同的虚拟地址但不同的物理地址。当上下文切换发生时可能需要刷新缓存或使用其他机制来解决潜在的地址冲突。 PIPT (Physically Indexed, Physically Tagged) 索引 使用物理地址进行缓存行索引。标签 使用物理地址进行缓存行标签比较。优点 没有虚拟地址空间重叠的问题。可以确保缓存的一致性和正确性。更适合多处理器系统因为它们共享同一物理内存空间。 缺点 更高的延迟因为在进行缓存访问之前必须完成地址转换。 **VIPT (Virtually Indexed, Physically Tagged) ** 索引 使用虚拟地址进行缓存行索引。标签 使用物理地址进行缓存行标签比较。优点 由于使用虚拟地址进行索引所以在某些情况下可以比PIPT更快。通过使用物理地址进行标签比较可以避免VIVT中的地址空间重叠问题。 缺点 更复杂因为它结合了虚拟和物理地址的使用。仍然需要等待部分地址转换完成才能确定是否命中。 注意在 ARM 架构中仅仅 L1 是 VIPTL2 和 L3 都是 PIPT。所以当有一个虚拟地址送进来MMU 在开始进行地址翻译的时候Virtual Index 就可以去 L1 cache 中查询了MMU 查询和 L1 cache 的 index 查询是同时进行的。如果 L1 Miss 了则再去查询 L2L2 还找不到则再去查询 L3。 3.5 Cache 替换策略有哪几种 缓存替换策略决定了当缓存行需要被替换时哪一个缓存行会被选中。这是为了在缓存中保持最有可能被使用的数据。以下是一些常见的缓存替换策略 最近最少使用 (LRU, Least Recently Used): LRU 策略替换最近最少使用的缓存行。该策略基于的思想是如果一个数据在过去没有被使用那么在未来很可能也不会被使用。 随机替换 (Random Replacement): 这种策略简单地随机选择一个缓存行来替换不基于任何数据的历史访问模式。 先进先出 (FIFO, First In First Out): FIFO 策略替换在缓存中存在时间最长的缓存行。但是它并不总是效果很好因为老数据可能仍然经常被访问。 最近未使用 (LFU, Least Frequently Used): LFU策略是替换在缓存中被访问次数最少的缓存行。这需要缓存持续跟踪每个缓存行的访问次数这可能会增加其实现的复杂性。 伪 LRU (Pseudo-LRU): 真正的 LRU 实现在硬件中可能会很复杂和昂贵。伪 LRU 是一种简化版本它试图近似 LRU 的行为但实现起来更简单。 OPT (Optimal Replacement Policy): 这是一种理论上的策略它总是选择将在未来最长时间内不被访问的缓存行进行替换。 在实际的系统中这是不可能的因为它需要对未来的数据访问有完美的知识。 其中LRU 和它的变种是最常用的缓存替换策略因为它通常能提供很好的性能。然而在硬件实现时真正的LRU可能会有些复杂和昂贵因此伪LRU和其他简化版本在某些情况下可能会更受欢迎。 3.6 详细描述 CPU 从发出内存请求到得到返回过程中Cache 和内存执行的完整流程 当使用 VIPT 的 L1 缓存和 PIPT 的 L2/L3 缓存时内存访问和管理过程会涉及多个步骤和组件。以下是从 CPU 发出内存请求到得到返回的所有环节的详细描述 CPU发出内存请求 当CPU需要访问某个内存地址时它首先发出一个虚拟地址因为现代系统使用虚拟内存来隔离进程和管理内存。 L1 Cache (VIPT) 访问 使用虚拟地址的部分索引L1缓存。同时地址转换从虚拟地址到物理地址开始。为此CPU查询TLB。 TLB查询 TLBTranslation Lookaside Buffer是一个小而快速的缓存它存储最近使用过的虚拟到物理地址的映射。如果TLB命中即如果需要的映射存在于TLB中则转换过程非常快物理地址立即可用。如果TLB未命中则需要访问页表。 页表访问 页表存储在主内存中并存储虚拟到物理地址的映射。如果所需的页面在物理内存中即页表中有一个有效的物理地址条目则地址转换完成。如果页面不在物理内存中会发生缺页中断。 缺页中断处理 当发生缺页中断时操作系统需要从磁盘中获取所需的页面。为了腾出空间操作系统可能需要选择一个物理内存中的页面进行置换即将其移出物理内存并保存到磁盘上。一旦页面被加载到物理内存中页表被更新并且缺页中断返回。 L1缓存标签比较 一旦有了物理地址就进行 L1 缓存的标签比较。如果 L1 命中数据从 L1 返回到 CPU。如果 L1 未命中请求传递到 L2。 L2 Cache (PIPT) 访问 使用物理地址索引和标记 L2。如果 L2 命中数据从 L2 返回到 CPU。如果 L2 未命中请求传递到 L3。 L3 Cache (PIPT) 访问 使用物理地址索引和标记 L3。如果 L3 命中数据从 L3 返回到 CPU。如果 L3 未命中请求传递到主内存。 主内存访问 如果数据不在任何缓存中它一定在主内存中。CPU 从主内存中读取数据并返回。 缓存行加载 当从更高层次的缓存或主内存中获取数据时通常会加载一个完整的缓存行而不仅仅是所需的数据。这是因为空间局部性原理即当某个数据项被访问时其附近的数据在不久的将来很可能也会被访问。当 L1 未命中但 L2 或 L3 命中时不仅会将数据返回到 CPU还会更新 L1 的缓存行。如果所有缓存级别都未命中当数据从主内存加载到 CPU 时所有级别的缓存都可能被更新。 缓存的替换 当缓存中没有可用空间来存储新的缓存行时需要决定哪一个旧的缓存行将被替换或丢弃。常见的策略有最近最少使用LRU、随机替换和先进先出FIFO。 在整个过程中虚拟到物理的地址转换和内存访问是两个主要的步骤。虚拟内存提供了进程隔离和内存管理的优势但也引入了地址转换的额外步骤。缓存尝试减少从主内存获取数据的时间因为这通常比从缓存获取数据要慢得多。 3.7 写操作中 Cache 分配策略有哪些最常用的策略是什么 缓存写策略决定了当处理器需要修改一个在缓存中存在的条目时应如何处理。写策略主要涉及两个关键问题 写命中Write Hit: 当需要写的数据在缓存中找到时怎么办 写未命中Write Miss: 当需要写的数据未在缓存中找到时怎么办 以下是几种常见的写策略 写命中时缓存的写策略 写回Write-Back 当缓存行被修改时它仅在缓存中被标记为“已修改”但不立即写入到主内存。只有当缓存行被替换出去时它才被写回到主内存。 写通Write-Through 一旦缓存行被修改数据也立即被写入到主内存中。 写未命中时缓存的写策略 写分配Write-Allocate 如果写操作未命中那么首先将相关的缓存行加载到缓存中然后再更新该缓存行。 不写分配No Write-Allocate 写未命中时数据直接被写入到主内存而不加载该缓存行。 “写回” 与 “写分配” 会结合使用最常用的策略 优点 降低了带宽需求因为只有在替换时才写回主内存。 缺点 更复杂的一致性管理因为主内存可能包含过时的数据。 在缓存替换时需要额外的写操作。 “写通” 与 “不写分配” 会结合使用 优点 主内存中的数据始终是最新的简化了缓存一致性的处理。 缺点 每次写都需要访问主内存可能导致较高的带宽需求和延迟。 3.8 读操作中 Cache 分配策略有哪些最常用的策略是什么 读操作的策略相对简单 总是分配Always Allocate: 当发生读未命中时总是从主存中加载数据块到缓存。这是最常用的策略因为当一次读操作未命中时很有可能后续的读写操作会访问相同的数据块。 不分配Never Allocate on a read miss: 读操作未命中时数据从主存返回到处理器但不存储在缓存中。这种策略在某些特定应用中可能有用其中连续读取的数据块只读取一次。 对于大多数常规应用和系统总是分配Always Allocate 策略是最常用和最有效的因为它利用了空间局部性原理如果一个数据项被访问那么其邻近的数据项在不久的将来可能也会被访问。 4. 缓存一致性Cache Coherence
4.1 缓存一致性Cache Coherence问题是怎么发生的如何解决 缓存一致性Cache Coherence问题主要发生在多处理器或多核系统中当多个处理器拥有对同一内存位置的本地缓存副本时。以下是问题的起源和示例场景 起源 多处理器或多核系统中每个处理器可能有自己的缓存。当多个处理器并行执行并且访问同一块内存时每个处理器可能在其缓存中维护这块内存的一个副本。如果一个处理器修改了其缓存中的值其他处理器的缓存中的副本就会变得过时或不一致。 示例场景 假设我们有两个处理器P1 和 P2它们都从同一个内存位置 M 读取数据并将其缓存。 时间 t0P1 和 P2 都读取 M 的值假设为 5并将其缓存在它们的本地缓存中。 时间 t1P1 修改 M 的值为 10并更新其本地缓存。 时间 t2如果没有适当的缓存一致性机制当 P2 再次读取 M 的值时它可能会从其本地缓存中读取旧值 5而不是更新后的值 10。 此种不一致性可能导致程序错误、难以追踪的行为以及性能下降。要解决缓存一致性问题需要确保以下两个条件满足 写入一致性Write Propagation 当一个值被一个处理器写入时这个写入操作需要在某个时间点传播到其他处理器的缓存。 事务串行性Transaction Serialization 如果两个处理器尝试在同一时间写入同一位置写入应该是串行的确保所有的处理器看到这两个写入的相对顺序是一致的。 为了维护缓存一致性多数现代多处理器系统实现了一致性协议如 MESI、MOESI、MSI 等这些协议通过定义缓存行的状态并规定在各种情况下的行为来确保一致性。 4.2 MESI 协议是什么他是如何保证缓存一致性的 MESI 协议是一个用于保证多处理器系统中缓存一致性的协议。名字MESI代表该协议定义的四个状态ModifiedM、ExclusiveE、SharedS 和 InvalidI。这四个状态描述了一个缓存行相对于主内存和其他处理器的缓存的状态。 如下图所示为 MESI 状态机图源 知乎内核补给站 以下是每个状态的解释和如何维护缓存一致性 Modified (M): 缓存行已被当前处理器修改并且与主存中的值不同。当其他处理器请求这个地址时拥有该地址的处理器将响应并提供更新后的值并将其状态更改为Invalid。 Exclusive (E): 缓存行未被修改与主存中的值匹配。该缓存行只在当前处理器的缓存中存在其他处理器的缓存中不存在这个地址。当处理器写入此缓存行时其状态会变为Modified。 Shared (S): 缓存行未被修改与主存中的值匹配。该缓存行可能存在于多个处理器的缓存中。当一个处理器写入一个Shared状态的缓存行时该行在该处理器的缓存中变为Modified而其他处理器的缓存中的该行变为Invalid。 Invalid (I): 缓存行无效或不一致。 当其他处理器写入同一内存地址时该缓存行将变为Invalid。 MESI 协议如何工作 当一个处理器想要读取或写入一个地址时它会在其本地缓存中查找该地址。如果找不到它会在总线上发出请求。根据该地址在其他处理器缓存中的状态和该处理器的请求类型读或写其他处理器会响应可能提供数据也可能使其缓存行无效。通过监听总线并根据其他处理器的请求和自己缓存中数据的状态更改自己缓存的状态每个处理器确保其缓存的一致性。