数组的访问速度通常比链表更快。 这主要是由于数组的缓存局部性。 我有两个疑问:
答案 0 :(得分:0)
实际上,它比你在问题中提出的简单模型更复杂。
首先,您可能有多个缓存层(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未命中数。
有用的链接:
维基百科关于CPU中缓存的文章:https://en.wikipedia.org/wiki/CPU_cache
关于同一主题的一篇陈旧但优秀的文章:http://arstechnica.com/gadgets/2002/07/caching/
各种缓存效果的图库:http://igoro.com/archive/gallery-of-processor-cache-effects/