实际上,它比您在问题中提出的简单模型要复杂一些。
首先,您可能有多个缓存层(L1、L2、L3),每个缓存层都有不同的特征。特别是,每个缓存的替换策略可能会使用不同的算法来权衡效率和复杂性(即成本)。
然后,所有现代操作系统都实现了虚拟内存机制。仅缓存数据和指令(这是 L1..L3 的用途)是不够的,还需要缓存虚拟地址和物理地址之间的关联(在 TLB 中,事务后备缓冲区)。
要了解局部性的影响,您需要考虑所有这些机制。
问题 1
内存和缓存之间交换的最小单位是缓存行。通常,它是 64 字节(但取决于 CPU 型号)。让我们假设缓存是空的。
如果你在一个数组上迭代,你需要为每 64 字节的缓存未命中付出代价。智能 CPU(和智能程序)可以分析内存访问模式并决定在缓存中预取连续的内存块以提高吞吐量。
如果您对列表进行迭代,则访问模式将是随机的,您可能会为每个项目支付一次缓存未命中。
问题 2
第一次访问时不会搜索整个数组并将其放入缓存中。只有第一个缓存行是。
但是,还有另一个因素需要考虑:TLB。页面大小取决于系统。典型值为 4 KB。第一次访问该数组时,将发生地址转换(其结果将存储在 TLB 中)。如果数组小于 4 KB(页面大小),则无需进行其他地址转换。如果它大于每页翻译一次。
将此与列表进行比较。多个项目适合同一页面 (4 KB) 的概率远低于数组。它们可以放入同一高速缓存行(64 字节)的可能性极低。
我认为计算复杂性很困难,因为可能还有其他因素需要考虑。但在这种复杂性中,您必须考虑缓存行大小(针对缓存未命中)和页面大小(针对 TLB 未命中)。
问题 3
缓存未命中是指给定的缓存行不在缓存中。它可能发生在 L1、L2 或 L3 级别。等级越高越贵。
当虚拟地址不在 TLB 中时会发生 TLB 未命中。在这种情况下,使用页表完成到物理地址的转换(成本高昂),并将结果存储在 TLB 中。
所以,是的,使用链表,您可能会为缓存和 TLB 未命中数支付比数组更多的费用。
有用的链接: