【发布时间】:2019-12-12 03:57:00
【问题描述】:
我正在阅读 Andrey Akinshin 的“Pro .NET Benchmarking”,有一件事让我感到困惑(第 536 页)——解释 cache associativity 如何影响性能。在一次测试中,作者使用了ints 的 3 个正方形数组 1023x1023、1024x1024、1025x1025,并观察到在 1024x1024 的情况下访问第一列的速度较慢。
作者解释(背景资料,CPU 是 Intel,具有 32KB 内存的 L1 缓存,它是 8-way associative):
当N=1024时,这个差值正好是4096字节;它等于 临界步幅值。这意味着从第一个 列匹配相同的八个 L1 缓存行。我们真的没有 缓存带来的性能优势,因为我们不能使用它 高效:我们只有 512 字节(8 个缓存行 * 64 字节缓存 行大小)而不是原来的 32 KB。当我们迭代 循环中的第一列,相应的元素相互弹出 缓存。当 N=1023 和 N=1025 时,我们没有问题 关键步幅不再:所有元素都可以保存在缓存中,这 效率更高。
所以看起来惩罚来自以某种方式缩小缓存,只是因为主内存无法映射到完整缓存。
这让我觉得很奇怪,在阅读了 wiki 页面后,我会说性能损失来自解决地址冲突。由于每一行都可以潜在地映射到同一个缓存行,因此这是一个又一个的冲突,CPU 必须解决这些问题——这需要时间。
因此我的问题是,这里的性能问题的真正本质是什么。缓存的可访问内存大小较小,或者整个缓存可用但 CPU 花费更多时间来解决与映射的冲突。还是有其他原因?
【问题讨论】:
-
所有访问的项目都映射到同一组缓存。该项目可以进入集合中 8 个缓存行中的任何一个,但由于在 64 个缓存行中仅使用 一个,因此只有 8 个缓存行可以保存数组中的数据(而不是 64* 8 = 512 个缓存行)。所以这就像缓存只有 512 个字节。它叫conflict miss。请记住:缓存不是完全关联的,相同的地址总是映射到相同的集合。
标签: performance caching cpu cpu-cache