【问题标题】:Does the CPU cache also load information from previous memory locations?CPU 缓存是否也从以前的内存位置加载信息?
【发布时间】:2016-02-15 12:35:20
【问题描述】:

如果执行以下代码:

int *array = new int[1000];
for (int i = 0; i < 1000; i++)
    array[i] = i * 2;

CPU 将数组存储在缓存中。但是,如果执行以下代码:

int *array = new int[1000];
for (int i = 1000-1; i >= 0; i--)
    array[i] = i * 2;

我想知道 CPU 是否也可以缓存数组,或者它是否只假设它存在于“向前”方向。

【问题讨论】:

  • 你不应该在意。性能例外,CPU 缓存对程序是透明的。
  • 缓存使用第 32 行或第 64 行等...(取决于硬件)字节。并且可能具有内存粒度,因此首先访问任何字节将完整(n 字节)内存块加载到缓存行中
  • 如果你把int array[1000];放在堆栈上,这是内存的一部分,被重复使用了很多次,所以它很可能在缓存中。如果您担心缓存不使用“新”,它通常比缓存未命中要慢得多。
  • @MarianSpanik 我完全清楚这一点。我只是将其作为可能尚未缓存的内存的示例。
  • @MarianSpanik 只是想补充一点,new[] 有一次 libc/您的操作系统试图为您提供可映射内存的惩罚;除此之外,从 CPU 的角度来看,堆与堆栈并没有什么特别之处;事实上,没有真正的理由假设new[] 在堆栈上分配;通常是这样,但是编译器可能会完全检测到它将是一个 1000 个整数数组并将其放在堆上。请参阅@lightningracesinorbit 最喜欢的东西。在没有 MMU 的机器上,堆和栈的概念甚至可能是无效的。

标签: c++ caching cpu cpu-cache


【解决方案1】:

有太多的 CPU 无法对此做出一般性假设,但是:

假设您使用的是常见的 x86 架构,那么缓存将包含的内容始终是缓存行大小的倍数,其中包含您访问的第一个导致缓存未命中的地址;对于向前访问。

根据内存访问预测的复杂程度,反向访问也可能被预取;谁来做这个预测取决于你的 CPU 架构、你的实际 CPU 实现和你的编译器。编译器“知道”哪些内存访问模式适用于给定的 CPU 代并确保内存访问按该顺序发生的情况并不少见。

对于您的算术情况,甚至可能有例如自动检测正在访问的四个连续、对齐的地址,并使用您的 CPU 支持的 SIMD 指令进行自动矢量化。这也会影响与访问 RAM 的对齐,这可能会进一步影响缓存行为..

此外,由于您似乎关心速度,因此您通常会允许编译器进行优化。在很多情况下,这会导致此类循环“反转”,甚至是 SIMD。

请注意,对于其他架构,这可能会有所不同:例如,90 年代中期有一个臭名昭著的摩托罗拉 DSP 系列具有相对简单的地址生成单元,并且如果您(或您的 C 编译器)知道如何告诉它向后工作;然后,可以选择将内存加载或存储与任何其他 CPU 指令“融合”,因此您的整个缓存将有效地由您手动指定内存访问模式的方式支配。

【讨论】:

    【解决方案2】:

    我想知道 CPU 是否也可以缓存数组,或者它是否只假设它存在于“向前”方向。

    CPU cache 以高速缓存行为单位(例如 32 个字或字节)。见this。您访问数组的顺序(增加或减少地址)并不重要。对缓存行的第一次访问将是一些缓存未命中(在您的前向和后向场景中),但不是下一个。

    编译器可能会优化和展开循环,和/或发出PREFETCH 机器指令。您可能小心(使用GCC)它的__builtin_prefetch(参见this),但如果您使用不当,甚至可能会减慢您的代码。

    【讨论】:

    • 应该强调的是,这与前向访问相同。
    • 即使没有编译器,CPU 本身也可能会发出一些自己的预取访问。大多数常见 CPU 中的这些流也可以采用任何一种方式
    【解决方案3】:

    是的,数组将被缓存。将数据作为高速缓存行大小的倍数进行高速缓存。因此,例如,如果缓存行大小为 8 字节,那么当您第一次访问内存位置时,无论您是尝试访问字节 0 还是字节 7,0-8 的所有内存位置都将被放入缓存中。

    【讨论】:

      【解决方案4】:

      缓存使用第 32 行或第 64 行等...(取决于硬件)字节。并且可能具有内存粒度,因此首先访问任何字节将完整(n字节)内存块加载到缓存行中

      【讨论】:

        猜你喜欢
        • 2010-10-15
        • 2016-04-08
        • 2012-07-01
        • 2019-09-24
        • 2013-03-06
        • 2015-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多