📜  虚拟索引物理标记 (VIPT) 缓存

📅  最后修改于: 2021-09-28 11:03:50             🧑  作者: Mango

先决条件:

  1. 高速缓存存储器
  2. 内存访问
  3. 分页
  4. 过渡后备缓冲器

重温缓存访问
当 CPU 生成物理地址时,对主存的访问先于对缓存的访问。使用此处显示的标记和索引/设置位在缓存中检查数据。这种从物理地址生成标记和索引位的缓存称为物理索引和物理标记(PIPT)缓存。当缓存命中时,内存访问时间显着减少。

缓存命中

Average Memory Access Time =
Hit Time + Miss Rate* Miss Penalty

这里,命中时间=缓存命中时间=访问缓存中的内存位置所需的时间
Miss Penalty= 将缓存行从主内存加载到缓存所需的时间
未命中率= \large \frac{No\ of\ Misses}{Total\ Memory\ Accesses}             在很长一段时间内

在当今的系统中,CPU 为进程生成逻辑地址(也称为虚拟地址)。使用 PIPT 缓存时,需要先将逻辑地址转换为其对应的物理地址,然后才能在 PIPT 缓存中搜索数据。这种从逻辑地址到物理地址的转换包括以下步骤:

  1. 检查 Transition Look Aside Buffer (TLB) 中的逻辑地址,如果它存在于 TLB 中,则从 TLB 中获取页面的物理地址。
  2. 如果不存在,则从物理内存访问页表,然后使用页表获取物理地址。

所有这些时间都会增加命中时间。因此,命中时间 = TLB 延迟 + 缓存延迟

TLB 和 PIPT 缓存:命中与未命中

PIPT 缓存的限制

  1. 这个过程是相当连续的,因此命中时间很长。
  2. 不适合内部级缓存。
  3. 任何系统都会频繁访问数据缓存,每次对数据进行 TLB 访问都会显着降低系统速度。

虚拟索引虚拟标记缓存
一个直接的解决方案似乎是虚拟索引虚拟标记 (VIVT)缓存。 VIVT 缓存直接检查缓存中的数据并获取它,而无需将其转换为物理地址,从而显着减少了命中时间。
在这样的缓存中,标签和索引将是 CPU 生成的逻辑/虚拟地址的一部分。现在可以使用 CPU 直接生成的地址来获取数据,从而显着减少了命中时间。
只有当缓存中不存在数据时,才会检查TLB,最终转换为物理地址后,将数据带入VIVT缓存中。因此,VIVT 的命中时间 = 缓存命中时间。

VIVT 缓存命中和未命中

VIVT 缓存的限制:

  1. TLB 包含重要标志,如脏位和无效位,因此即使使用 VIVT 缓存,也需要检查 TLB。
  2. 上下文切换时的大量缓存未命中:由于缓存特定于逻辑地址,并且每个进程都有自己的逻辑地址空间,因此两个进程可以使用相同的地址但引用不同的数据。
    请记住,这与为每个进程设置页表的原因相同。这意味着对于每次上下文切换,都需要刷新缓存,并且每次上下文切换都伴随着大量的缓存未命中,这既耗时又增加了命中时间。

这些问题的解决方案是虚拟索引物理标记缓存(VIPT Cache)。文章的下一部分将介绍 VIPT Cache、VIPT Cahe 中的挑战和一些解决方案

虚拟索引物理标记缓存 (VIPT)
VIPT 缓存使用来自物理地址和索引的标记位作为来自逻辑/虚拟地址的索引。使用虚拟地址搜索缓存并获得物理地址的标记部分。用虚拟地址查找TLB,得到物理地址。最后,将从VIPT缓存中获取的物理地址的标签部分与从TLB中获取的物理地址的标签进行比较。如果它们都相同,则是缓存命中,否则是缓存未命中。

VIPT 缓存命中和未命中

由于 TLB 的大小比缓存小,因此 TLB 的访问时间将小于 Cache 的访问时间。因此,命中时间=缓存命中时间。
VIPT缓存在命中时与VIVT缓存相同,解决了VIVT缓存问题:

  1. 由于 TLB 也是并行访问的,因此可以同时检查标志。
  2. VIPT 缓存使用部分物理地址作为索引,由于系统中的每次内存访问都对应一个唯一的物理地址,因此缓存中可以存在多个进程的数据,因此无需为每次上下文切换刷新数据。

可以想到的一个问题是,当缓存命中但 TLB 未命中时,这将需要对物理内存中的页表进行内存访问。这种情况很少发生,因为 TLB 仅存储位(地址和标志)作为其条目,与缓存的整个内存块(几个字节)相比,它需要的空间要少得多。因此,TLB 中的条目数量远多于缓存中的缓存块,即 TLB 中的条目\subseteq                缓存标签目录中的条目。

虚拟索引物理标记缓存的优点

  1. 避免顺序访问减少命中时间
  2. 在频繁访问缓存的数据缓存中很有用
  3. 避免上下文切换时缓存未命中
  4. TLB 标志可以与缓存访问并行访问

虚拟索引物理标记缓存的挑战
VIPT 缓存中的虚拟索引会带来挑战。一个进程可以有两个虚拟地址映射到同一个物理位置。这可以在 Linux 中使用 mmap 来完成:

mmap(virtual_addr_A,4096,file_descriptor,offset)
mmap(virtual_addr_B,4096,file_descriptor,offset)

以上两行将 file_descriptor 指向的文件映射到两个不同的虚拟地址但物理地址相同。由于这两个虚拟地址不同并且缓存是虚拟索引的,因此这两个位置可能会被索引到缓存中的不同位置。这将导致数据块有两个副本,并且当这些位置更新时,数据将不一致。这个问题称为别名。别名也可能发生在两个进程的共享块中。

以下是解决问题的四种解决方案:

  1. 第一种解决方案需要在更新内存位置时使缓存中的任何其他数据副本无效。
  2. 第二种解决方案是在更新内存位置时更新缓存中的所有其他数据副本
    请注意,第一个和第二个解决方案需要检查是否有任何其他位置映射到相同的物理内存位置。这需要将虚拟地址转换为物理地址;但 VIPT 旨在避免翻译,因为它会增加命中延迟。
  3. 第三种解决方案涉及减少缓存大小。请记住,在虚拟地址到物理地址的转换过程中,虚拟地址的页面偏移量与物理地址的页面偏移量相同。这意味着两个虚拟地址也将具有相同的页偏移量。为确保两个虚拟地址映射到缓存中的同一个索引,索引字段必须完全在页偏移量部分。

演示别名的示例:

Consider a system with:
32 bit virtual address,
block size 16 Bytes and page size 4 KB
(i) Direct Mapped Cache: 64 KB
(ii) Direct Mapped Cache: 4 KB
(iii) Direct Mapped Cache: 2 KB

(i) 在 32 位虚拟地址中,对于 64KB 的直接映射缓存,
位 15 到 4 用于索引,
位 11 到 0 是页面偏移量(这意味着对于指向相同 PA 的任何两个 VA,12 个 LSB 位将相同)。

6 KB 直接映射缓存

两个虚拟地址可以将 0x0045626E 和 FF21926E 映射到同一个物理地址。第一个地址将被索引到 (626) H缓存行,第二个地址将被索引到 (926) H 。这显示了系统的 64KB 直接映射缓存发生了别名。还要注意,最后 12 位在两个寻址中是相同的,因为它们已映射到相同的物理地址,最后 12 位形成页面偏移量,这对于两个虚拟地址都是相同的。

(ii) 在 32 位虚拟地址中,对于 4KB 直接映射缓存,第 11 到 4 位是索引,第 11 到 0 位是页偏移量(这意味着对于指向同一个 PA 的任意两个 VA,12 LSB 位将是相同的)。

4 KB 直接映射缓存

两个地址可以是 0x12345678 和 0xFEDCB678。请注意,12 个 LSB 位是相同的,即 (678) H 。由于对于 2KB 直接映射缓存,索引位完全是同一页偏移量的一部分,因此两个虚拟地址将映射的缓存索引将是相同的。因此,一次只保留一个副本并且不会发生混叠。

(iii) 以下是系统的 2KB 直接映射缓存的表示,没有显示混叠。因此,任何大小小于或等于 4KB 的直接映射缓存都不会导致混叠。

2 KB 直接映射缓存

4. 别名的第三种解决方案要求缓存更小,更小的缓存会导致更多的缓存未命中。解决方案 1,
2 和 3 是基于硬件的。另一种称为页面颜色/缓存着色的解决方案是软件解决方案
由操作系统实现以在不限制缓存大小的情况下解决别名问题。如果是 64KB 缓存 16
需要颜色以确保不会发生锯齿。进一步阅读:ARMv6 上的页面着色