最近,我对面向数据的设计产生了兴趣。到目前为止,我已经阅读了一些关于该主题的文章和出版物。我了解缓存是如何工作的以及它是如何构建的(通常是抽象的)L1、L2、L3,什么是缓存行,什么是 N 路关联,为什么缓存如此高效等等。不幸的是,我在理论上理解这一切,看例子我不能理解它们。另外,我不能将它合二为一,因此我的问题。
我在互联网上遇到了一个例子(http://igoro.com/archive/gallery-of-processor-cache-effects/)(Example3 -> code belowe)。
我的问题:
我不明白为什么性能会随着数组大小的增加而降低(参见链接中的图片)。
毕竟,缓存行是 64 字节(我在某处读到这是大小),所以它应该总是适合 L1。我不明白数据大小和给定缓存级别之间的关系,因为缓存行是 64 字节 + 预取器 256 字节(我在某处读到这是大小),所以一切都适合 L1。(如果缓存线很忙,那么我们可以删除它并添加一个新的需要的缓存线。)。
int steps = 64 * 1024 * 1024; // Arbitrary number of steps int lengthMod = arr.Length - 1; for (int i = 0; i < steps; i++) { arr[(i * 16) & lengthMod]++; // (x & lengthMod) is equal to (x % arr.Length) }
你可以看到在 32kB 和 4MB 之后明显下降——这是我机器上 L1 和 L2 缓存的大小。
另外:我不明白如何将数据加载到缓存中。我们假设所需的数据不在缓存的任何级别,并且整个缓存是空的。
数据会先加载到 L3,然后再加载到 L2 和 L1(如果合适的话)?还是只达到L1?
我想答案尚不清楚,取决于 CPU 和缓存设计,但如果有人能以某种一般方式描述它,我将不胜感激。