CPU Cache 数据写入的两种方式
在现代计算机体系结构中,CPU Cache 是一个至关重要的组件,它的存在极大地提高了 CPU 与主存之间的数据传输效率,有效缓解了 CPU 与主存之间的速度差异,对于提升整个计算机系统的性能发挥着不可忽视的作用。其中,CPU Cache 数据写入主要有两种方式:写直达(Write-Through)和写回(Write-Back)。
一、写直达(Write-Through)
1. 基本原理
写直达是一种较为直接的 Cache 数据写入机制。当 CPU 发起写操作时,数据会同时被写入到 Cache 和主存中。这意味着,对于每一次写操作,数据会立即更新到主存,保证了主存和 Cache 中的数据始终处于一致状态。其核心在于不允许数据只存储在 Cache 中而不更新主存,从而确保了数据的一致性,但也带来了一些特殊的性能特点和设计考虑。
2. 操作流程
- 写操作发起:当 CPU 执行写操作时,首先会将数据存储在 Cache 中相应的位置。Cache 作为高速缓存,存储数据的目的是为了加速后续的访问,但在写直达模式下,这并不是唯一的操作。
- 主存更新:在数据写入 Cache 的同时,该数据会通过系统总线传输到主存,并更新主存中相应的存储位置。这个过程是同步的,必须等待主存更新完成后,写操作才算完成。例如,在一个简单的处理器架构中,假设 CPU 要将一个值存储在地址为
0x1000
的位置,它会先将该值存储在 Cache 中对应的映射位置,然后通过系统总线,将相同的数据存储在主存中地址为0x1000
的位置。
3. 优点
- 数据一致性保证:
- 写直达方式最大的优势在于其能确保数据的一致性。在多处理器系统或具有多个硬件设备共享主存的环境中,这一点尤为重要。因为主存始终存储着最新的数据,所以不同处理器或设备访问相同地址的数据时,不会出现数据不一致的情况。例如,在一个多处理器服务器中,处理器 A 对某个共享变量进行了修改,采用写直达方式,处理器 B 能立即从主存中读取到更新后的数据,避免了数据不一致导致的错误。
- 对于一些对数据一致性要求极高的应用程序,如实时金融交易系统,数据的一致性直接关系到交易的准确性和可靠性,写直达可以确保每一次数据修改都能即时反映在主存中,避免了因数据不一致而造成的交易错误或数据损坏。
- 实现简单性:
- 从硬件设计和实现的角度来看,写直达相对简单。不需要复杂的状态标记和额外的控制逻辑来跟踪 Cache 中数据的修改状态。硬件只需要简单地将数据同时写入 Cache 和主存,不需要考虑后续的写回操作,减少了硬件设计的复杂性和成本。
- 在一些简单的计算机系统或对硬件成本敏感的嵌入式系统中,如简单的微控制器或低端的物联网设备,写直达的简单实现可以降低硬件开发成本和设计难度。
4. 缺点
- 性能瓶颈:
- 由于每次写操作都要更新主存,会导致系统总线的频繁使用。主存的访问速度相对 Cache 来说要慢得多,可能会引入较长的延迟。对于那些对性能要求较高,且写操作频繁的应用程序,这会成为性能瓶颈。例如,在一个大规模的数据处理程序中,频繁的写操作会导致大量的时间花费在等待主存更新上,而不是 CPU 的计算上。
- 实验表明,在一些科学计算程序中,如流体力学模拟程序,大量的计算过程中会有频繁的中间结果更新,如果采用写直达,会因为频繁的主存更新而大大降低程序的执行效率,可能会导致整体性能下降 30% 甚至更多。
- 资源浪费:
- 对于那些被频繁修改的数据,即使最终只在 Cache 中使用,也会反复更新主存。这会浪费大量的系统带宽,因为每次更新都需要通过系统总线传输数据,而这些传输可能是不必要的。
- 例如,在图形渲染程序中,可能会对同一像素数据进行多次修改,如果每次修改都要更新主存,会占用大量的系统总线带宽,而实际上只需要最终结果更新到主存即可,这种情况下,写直达会造成不必要的资源浪费。
二、写回(Write-Back)
1. 基本原理
写回方式是一种更注重性能的 Cache 数据写入机制。在这种方式下,当 CPU 对 Cache 中的数据进行写操作时,仅更新 Cache 中的数据,而不会立即更新主存。只有当该数据所在的 Cache 行需要被替换时,才会将修改后的数据写回到主存。这种方式通过延迟主存的更新,减少了主存的访问次数,提高了写操作的性能,但也带来了数据一致性维护的挑战。
2. 操作流程
- 写操作发起:当 CPU 进行写操作时,数据被写入 Cache 中相应的位置,同时将该 Cache 行标记为“已修改”(Dirty)。这个标记用于后续判断该 Cache 行是否需要写回主存。例如,在一个基于写回机制的 Cache 中,当 CPU 将新数据存储在某个 Cache 行时,会将该 Cache 行的“脏”标记置为 1,表示该 Cache 行中的数据已被修改。
- Cache 行替换:当 Cache 满或需要替换某个 Cache 行时,会检查该 Cache 行是否被标记为“已修改”。如果是,则将该 Cache 行的数据写回主存,然后再进行替换操作;如果不是,则直接替换,无需写回主存。在替换时,会根据 Cache 的替换策略(如 LRU - 最近最少使用策略)来决定替换哪个 Cache 行。
3. 优点
- 性能提升:
- 写回方式通过减少主存的访问次数,显著提高了写操作的性能。对于那些对数据进行多次修改的程序,这种优势尤为明显。在缓存命中的情况下,写操作只涉及到 Cache 的访问,避免了每次写操作都要访问主存的开销。
- 例如,在一个文本编辑程序中,用户可能会频繁修改文档内容,这些修改会存储在 Cache 中,只有在保存文件或 Cache 行需要替换时才会更新主存,从而提高了用户体验和程序性能。在数据库系统中,对于频繁更新的数据记录,写回方式可以在数据最终落盘前在 Cache 中进行多次修改,提高了数据库的更新性能。
- 减少总线使用:
- 由于不是每次写操作都更新主存,减少了系统总线的使用频率,这对于系统的整体性能和功耗都有好处。在高性能计算机系统中,减少总线使用可以降低系统的延迟和功耗。
- 例如,在大型数据中心服务器中,大量的数据处理操作会产生频繁的写操作,写回方式可以减少系统总线的负载,提高系统的吞吐量,同时降低服务器的功耗,减少运营成本。
4. 缺点
- 数据一致性问题:
- 由于数据不是立即更新到主存,这可能会导致数据不一致性。在多处理器系统中,不同处理器的 Cache 可能存储着不同版本的数据,需要额外的协议来维护数据一致性。例如,在多处理器并发执行的情况下,处理器 A 修改了 Cache 中的数据,但还未写回主存,处理器 B 可能会读取到旧数据,从而产生错误。
- 为了解决这个问题,通常需要使用复杂的缓存一致性协议,如 MESI(Modified、Exclusive、Shared、Invalid)协议。这些协议通过状态标记和消息传递来确保不同处理器的 Cache 之间以及 Cache 与主存之间的数据一致性,增加了硬件设计和实现的复杂性。
- 硬件复杂性增加:
- 写回方式需要为每个 Cache 行添加“已修改”标记,并且需要更复杂的逻辑来管理 Cache 行的替换和写回操作。例如,在硬件设计中,需要有专门的硬件模块来检查 Cache 行是否为“已修改”状态,以及何时将其写回主存。
- 在一些复杂的处理器设计中,需要更复杂的硬件电路来实现写回策略,包括缓存替换策略和写回操作的控制逻辑,这增加了硬件设计的难度和成本。
三、对比与应用场景分析
1. 性能对比
- 性能差异的本质:
- 写直达方式的性能主要受限于主存的访问速度,因为每次写操作都要等待主存更新。而写回方式主要取决于 Cache 的性能,只有在 Cache 行替换时才会涉及主存操作,因此在写操作频繁的情况下,写回方式可以充分利用 Cache 的高速性能,减少性能瓶颈。
- 在一个实验中,使用写直达和写回两种方式对一个内存密集型的应用程序进行测试,结果显示,当写操作频率达到一定程度后,写回方式的性能比写直达方式高出约 50% 至 80%,因为写回方式可以减少大量不必要的主存访问。
- 实际性能影响因素:
- 性能还受到 Cache 大小、Cache 行大小、替换策略和系统总线带宽等因素的影响。例如,在一个具有较大 Cache 且使用高效替换策略的系统中,写回方式的优势会更加明显;而在系统总线带宽较低的情况下,写直达可能会因为频繁占用总线而使性能下降更严重。
2. 数据一致性对比
- 一致性维护机制:
- 写直达通过始终更新主存来保证数据一致性,而写回需要额外的一致性协议。写回的一致性协议通常需要处理器之间的通信和协调,如通过总线发送消息来通知其他处理器某个 Cache 行的状态变化,这可能会引入额外的延迟和复杂性。
- 在分布式系统中,如集群计算环境,写回方式的一致性协议需要在多个节点之间协调,增加了分布式一致性的维护难度,而写直达可能会因为每次更新主存而更容易保证节点间的数据一致性。
- 一致性问题的影响:
- 数据不一致可能会导致程序错误,如在并发编程中,不同线程或进程可能会读取到错误的数据,从而产生不可预测的结果。对于写回方式,这种不一致性风险更高,需要更谨慎的设计和更复杂的一致性协议来避免错误。
3. 应用场景
- 写直达的应用场景:
- 实时系统:在一些实时性要求高且对数据一致性极其敏感的系统中,如工业控制、航空航天控制系统,写直达是首选。这些系统中,数据的准确性和一致性至关重要,任何数据延迟或不一致都可能导致严重的后果,而且写操作相对较少,性能不是主要的考虑因素。
- 简单嵌入式系统:对于一些资源有限、硬件成本敏感且对性能要求不高的嵌入式系统,如简单的传感器节点、智能家电控制器等,写直达的简单性可以降低硬件设计和开发成本,同时满足数据一致性需求。
- 写回的应用场景:
- 高性能计算:在高性能计算领域,如超级计算机、科学计算集群等,写回方式可以充分利用 Cache 的高速性能,提高计算速度。例如,在高性能计算的矩阵运算、深度学习训练等任务中,大量的数据修改可以在 Cache 中完成,减少主存访问,提高系统性能。
- 多处理器系统:在多处理器服务器、多核处理器架构中,虽然需要复杂的一致性协议,但写回方式可以通过减少主存访问来提高系统的整体性能。在服务器应用程序,如 Web 服务器、数据库服务器等,写回方式可以提高数据处理的吞吐量。
四、疑难解答
写回策略下,
如果当发生写操作时,数据所对应的 Cache Block 里存放的是「别的内存地址的数据」的话,就要检查这个 Cache Block 里的数据有没有被标记为脏的。如果是脏的话,我们就要把这个 Cache Block 里的数据写回到内存,然后再把当前要写入的数据,先从内存读入到 Cache Block 里,然后再把当前要写入的数据写入到 Cache Block,最后也把它标记为脏的。
看小林coding面经的时候,对加粗斜体内容不是很理解,看了超链接指向的回答写的也不太清楚。
我的理解是:我们要更新的数据可能并不能填充满cache line,常见的cache line大小是64k,我们数据可能只占4k或者8k,那么我们就要把原先的一整行cache line都先读进来,然后再更改cache line中的某一部分。