2026年10月押题密卷 · 选择题
以下关于Cache 的叙述中,正确的是( )。
Cache 的功能是提高CPU数据输入/输出的速率,突破所谓的“冯 ·诺依曼瓶颈”,即CPU与存储系统间 数据传送带宽限制。高速存储器能以极高的速率进行数据的访问,但因其价格高昂,如果计算机的内 存完全由这种高速存储器组成,则会大大增加计算机的成本。通常在CPU和内存之间设置小容量的 Cache。Cache 容量小但速度快,内存速度较低但容量大,通过优化调度算法,系统的性能会大大改 善,仿佛其存储系统容量与内存相当而访问速度近似Cache。 Cache 通常采用相联存储器(Content Addressable Memory,CAM)。CAM是一种基于数据 内容进行访问的存储设备。当对其写入数据时,CAM能够自动选择一个未用的空单元进行存储;当要 读出数据时,不是给出其存储单元的地址,而是直接给出该数据或者该数据的一部分内容,CAM对所 有存储单元中的数据同时进行比较,并标记符合条件的所有数据以供读取。由于比较是同时、并行进 行的,所以,这种基于数据内容进行读/写的机制,其速度比基于地址进行读/写的方式要快很多。 ①Cache基本原理 使用Cache 改善系统性能的依据是程序的局部性原理。程序访问的局部性有两个方面的含义, 分别是时间局部性和空间局部性。时间局部性是指如果一个存储单元被访问,则可能该单元会很快被 再次访问。这是因为程序存在着循环。空间局部性是指如果一个存储单元被访问,则该单元邻近的单 元也可能很快被访问。这是因为程序中大部分指令是顺序存储、顺序执行的,数据一般也是以向量、 数组、树、表等形式簇聚地存储在一起的。 根据程序的局部性原理,最近的、未来要用的指令和数据大多局限于正在用的指令和数据,或 是存放在与这些指令和数据位置上邻近的单元中。这样,就可以把目前常用或将要用到的信息预先放 在Cache 中。当CPU需要读取数据时,首先在Cache 中查找是否有所需内容,如果有,则直接从Cache 中读取;若没有,再从内存中读取该数据,然后同时送往CPU和Cache。 如果CPU需要访问的内容大 多都能在Cache 中找到(称为访问命中),则可以大大提高系统性能。 如果以h 代表对Cache 的访问命中率("1-h" 称为失效率,或者称为未命中率),t₁ 表示Cache 的周期时间,七₂表示内存的周期时间,以读操作为例,使用“Cache+ 主存储器”的系统的平均周期为 t3。则: t₃=t₁×h+t₂×(1-h) 系统的平均存储周期与命中率有很密切的关系,命中率的提高即使很小也能导致性能上的较大 改善。 例如,设某计算机主存的读/写时间为100ns, 有一个指令和数据合一的Cache, 已知该Cache 的读/写时间为10ns, 取指令的命中率为98%,取数的命中率为95%。在执行某类程序时,约有1/5 指令需要存/取一个操作数。假设指令流水线在任何时候都不阻塞,则设置Cache 后,每条指令的平 均访存时间约为: (2%×100ns+98%×10ns)+1/5×(5%×100ns+95%×10ns)=14.7ns ②映射机制 当CPU发出访存请求后,存储器地址先被送到Cache 控制器以确定所需数据是否已在Cache 中, 若命中则直接对Cache 进行访问。这个过程称为Cache 的地址映射(映像)。在Cache 的地址映射中, 主存和Cache 将均分成容量相同的块(页)。常见的映射方法有直接映射、全相联映射和组相联映射。 ·直接映射。直接映射方式以随机存取存储器作为Cache存储器,硬件电路较简单。直接映射是 一种多对一的映射关系,但一个主存块只能够复制到Cache 的一个特定位置上去。例如,某Cache 容量为16KB(即可用14位表示),每块的大小为16B(即可用4位表示),则说明其可分为1024块(可 用10位表示)。主存地址的最低4位为Cache 的块内地址,然后接下来的中间10位为Cache 块号。如 果主存地址为1234E8F8H(一共32位),那么,最后4位就是1000(对应十六进制数的最后一位"8"), 而中间10位,则应从E8F(11101 0001111) 中获取,得到1010001111。因此,主存地址为 1234E8F8H的单元装入的Cache 地址为101000111 11000。 直接映射的关系可以用下列公式来表示: K=I mod C 其中,K为Cache的块号,I为主存的页号,C为Cache的块数。 直接映射方式的优点是比较容易实现,缺点是不够灵活,有可能使Cache 的存储空间得不到充 分利用。例如,假设Cache 有8块,则主存的第1页与第17页同时复制到Cache 的第1块,即使Cache 其他块空闲,也有一个主存页不能写入Cache。 ·全相联映射。全相联映射使用相联存储器组成的Cache 存储器。在全相联映射方式中,主存的 每一页可以映射到Cache 的任一块。如果淘汰Cache 中某一块的内容,则可调入任一主存页的内容, 因而较直接映射方式灵活。 在全相联映射方式中,主存地址不能直接提取Cache 块号,而是需要将主存页标记与Cache 各 块的标记逐个比较,直到找到标记符合的块(访问Cache 命中),或者全部比较完后仍无符合的标记 (访问Cache 失败)。因此,这种映射方式速度很慢,失掉了高速缓存的作用,这是全相联映射方式 的最大缺点。如果让主存页标记与各Cache 标记同时比较,则成本又太高。全相联映像方式由于比较 器电路难于设计和实现,故只适用于小容量的Cache。 ·组相联映射。组相联映射是直接映射和全相联映射的折中方案。它将Cache 中的块再分成组, 通过直接映射方式决定组号,通过全相联映射的方式决定 Cache 中的块号。在组相联映射方式中,主存中一个组内的页数与Cache 的分组数相同。 例如,容量为64块的Cache 采用组相联方式映像,每块大小为128个字,每4块为一组,即Cache 分为64/4=16组。若主存容量为4096页,且以字编址。首先,根据主存与Cache 块的容量需一致, 即每个内存页的大小也是128个字,因此一共有128×4096个字(219个字),即主存地址需要19位。 因为Cache 分为16组,所以主存需要分为4096/16=256组(每组16页),即28组,因此主存组号需8 位。 按照上述划分方法,主存每一组的第1页映射到Cache 的第1组,主存每一组的第2页映射到 Cache 的第2组,依此类推。因为主存中一个组内的页数与Cache 的分组数相同,所以主存每一组的 最后一页映射到Cache 的最后一组。 要注意的是,有关组相联映射的划分方法不止一种。例如,还有一种方式是主存不分组,而是 根据下列公式直接进行映射: J=I mod Q 其中,J 为Cache 的组号,I为主存的页号,Q为Cache 的组数。 在组相联映射中,由于Cache 中每组有若干可供选择的块,因而它在映像定位方面较直接映像 方式灵活:每组块数有限,因此付出的代价不是很大,可以根据设计目标选择组内块数。 ③替换算法 当Cache 产生了一次访问未命中之后,相应的数据应同时读入CPU和Cache。 但是当Cache 已存 满数据后,新数据必须替换(淘汰)Cache 中的某些旧数据。最常用的替换算法有以下三种。 ·随机算法。这是最简单的替换算法。随机算法完全不管Cache 块过去、现在及将来的使用情况, 简单地根据一个随机数,选择一块替换掉。 ·先进先出(First In and First Out,FIFO)算法。按调入Cache 的先后决定淘汰的顺序, 即在需要更新时,将最先进入Cache 的块作为被替换的块。这种方法要求为每块做一记录,记下它们 进入Cache 的先后次序。这种方法容易实现,而且系统开销小。其缺点是可能会把一些需要经常使用 的程序块(如循环程序)替换掉。 ·近期最少使用(Least Recently Used,LRU)算法。LRU 算法是把CPU 近期最少使用的块作 为被替换的块。这种替换方法需要随时记录Cache 中各块的使用情况,以便确定哪个块是近期最少使 用的块。 LRU算法相对合理,但实现起来比较复杂,系统开销较大。通常需要对每一块设置一个称为 “年龄计数器”的硬件或软件计数器,用于记录其被使用的情况。 ④写操作 因为需要保证缓存在Cache 中的数据与内存中的内容一致,相对读操作而言,Cache 的写操作 比较复杂,常用有以下几种方法。 ·写直达(write through)。 当要写Cache 时,数据同时写回内存,有时也称为写通。当某一 块需要替换时,也不必把这一块写回到主存中去,新调入的块可以立即把这一块覆盖掉。这种方法实 现简单,而且能随时保持主存数据的正确性,但可能增加多次不必要的主存写入,会降低存取速度。 ·写回(write back)。CPU 修改Cache 的某一块后,相应的数据并不立即写入内存单元,而是 当该块从Cache 中被淘汰时,才把数据写回到内存中。在采用这种更新策略的Cache 块表中,一般有 一个标志位,当一块中的任何一个单元被修改时,标志位被置“1”。在需要替换掉这一块时,如果标 志位为“1”,则必须先把这一块写回到主存中去之后,才能再调入新的块;如果标志位为“0”,则这 一块不必写回主存,只要用新调入的块覆盖掉这一块即可。这种方法的优点是操作速度快,缺点是因 主存中的字块未随时修改而有可能出错。 ·标记法。对Cache 中的每一个数据设置一个有效位。当数据进入Cache 后,有效位置“1”;而 当CPU要对该数据进行修改时,数据只需写入内存并同时将该有效位置“0”。当要从Cache 中读取数 据时需要测试其有效位,若为"1"则直接从Cache 中取数,否则,从内存中取数。