物理地址不连续时cpu如何缓存

问题描述 投票:0回答:1

例如我的进程中使用连续虚拟地址的数组。但是CPU在物理地址上使用CPU缓存,该地址在我的数组中可能不连续。在这种情况下,CPU 缓存是否会失败,或者 CPU 或操作系统是否有帮助?

他们会做某事还是放手?

linux-kernel cpu cpu-cache
1个回答
0
投票

缓存不会“失败”,它们已经被设计为缓存可能分散的行,而不仅仅是大的连续数组。 (即使您有同一物理页面的多个虚拟映射,也可以避免同音异义/同义词问题。)

同一数组的某些行可能在二级缓存中具有相同的索引(映射到同一组),即使它们在虚拟地址中仅相距 4K,但在物理地址中相距某些较大的 2 的幂的倍数。但是集合关联(不是直接映射)缓存可以处理这个问题,除非你非常不幸,然后你可能会得到一些你没有预料到的额外驱逐(和冲突未命中)。

大页/大页 (

madvise(MADV_HUGE)
) 将提示 Linux 内核对内存区域使用透明大页,因此连续的虚拟是 2MiB 块中的连续物理块(例如在 x86-64 上),而不是 4K。


许多 x86 CPU 至少具有 L1d,它具有足够的关联性且足够小,以至于 VIPT = PIPT,所有索引位都来自地址的页内偏移部分,因此对同一组进行别名或不仅仅取决于地址的页内偏移量部分。 (标签是物理的,因此当您有同一物理页的两个虚拟映射时,您可以获得缓存命中。) 其他一些 ISA 依赖于操作系统的帮助,例如页面着色,使虚拟页号的低 1 或 2 位与物理(页框)号匹配)以避免 L1i/L1d 中的缓存同义/同音问题。这使得地址的有效页内偏移部分加宽了几个位,以便对集合进行索引,这对于缓存冲突未命中也很重要。 (请参阅

虚拟索引物理标记缓存同义词,了解如何通过缓存索引和标记位进行调整的示例。)

在Linux内核中

PAGE_SHIFT是移位计数,这样

addr >> page_shift
将移出所有页内偏移位,留下非大页的页号。还使用“页分割”描述页号和地址的页内偏移位之间的中断位置。它是地址中页内偏移位的数量。)

但是外部缓存(例如 L2 和 L3)使用更多索引位。它们纯粹在物理地址 (PIPT) 上工作,virt 到 phys 与 L1d 访问并行发生,因此在 L1 未命中的情况下,它已经在 L2 访问之前完成。因此,使它们成为 VIPT 并没有速度优势,因此 PIPT 对于 L1 以外的缓存级别几乎是通用的。

这确实使得索引(从而为同一组别名)依赖于连续的物理或不依赖。对于单个连续地址,

size = cache_size/associativity

中的每一行都映射到不同的集合,因此不会发生冲突。例如对于 Skylake 的 256 KiB 4 路 L2 缓存,即 64K 或 1024 组。

大型共享末级缓存(典型 x86 中的 L3)通常使用物理地址所有高位的哈希函数进行索引,因此它们对是否连续的物理地址不太敏感,并且即使有很多冲突也能抵抗冲突丢失例如,“热”高速缓存行位于分散在各个不同页面的前 64 个字节中。 (与 L1d 和 L2 缓存不同,这些缓存行只能由总集合中的一个 (L1d) 或几个 (L2) 进行缓存,而其他缓存则不使用。)对于分布式 L3 缓存(例如 Intel,每个核心旁边都有一个切片) ,一个好的哈希函数有望避免环形总线上的一站或网格太热。

© www.soinside.com 2019 - 2024. All rights reserved.