【问题标题】:What is the cost of memory access?内存访问的成本是多少?
【发布时间】:2010-06-14 16:33:01
【问题描述】:

我们喜欢认为内存访问是快速且持续的,但在现代架构/操作系统上,这不一定是正确的。

考虑以下 C 代码:

int i = 34;
int *p = &i;

// do something that may or may not involve i and p

{...}

// 3 days later:

*p = 643;

如果在 CPU 指令中最后一次分配的估计成本是多少

  • i 在一级缓存中,
  • i 在二级缓存中,
  • i 在三级缓存中,
  • i 在 RAM 中,
  • i 被调出到 SSD 磁盘,
  • i 被调出到传统磁盘?

i 还能在哪里?

当然数字不是绝对的,但我只对数量级感兴趣。我试着在网上搜索,但这次谷歌并没有祝福我。

【问题讨论】:

  • 呃,如果它被调出,访问成本是不确定的......
  • 老兄,如果你的程序需要三天才能运行,那么你的问题比担心要花多长时间才能进入p :)
  • Where else can i be? 在网络上的某个地方?半个地球?

标签: language-agnostic memory hardware


【解决方案1】:

这里有一些确切的数字,表明确切的时间因 CPU 系列和版本而异:http://www.agner.org/optimize/

这些数字是一个很好的指南:

L1           1 ns
L2           5 ns
RAM         83 ns
Disk  13700000 ns

作为一个信息图来给你数量级:

(src http://news.ycombinator.com/item?id=702713)

【讨论】:

  • 只是我还是那张图片只是一个红色的大矩形?
  • @paxdiablo 是的,你真的需要点击它才能看到 L1 的左上角
  • 信息图可能是正确的,但引用的 13700 ns 数字不是。它更像是 10,000,000ns (10ms)。来源:google.com/moderator/#9/…
  • 编辑 - 放大后的信息图甚至会说出来。 13.7 毫秒。 1ms = 1,000,000ns。
  • @Morgan Tocker thx;你能确认我已经正确纠正了吗?
【解决方案2】:

Norvig 从 2001 年开始有一些 values。从那以后情况发生了一些变化,但我认为相对速度仍然大致正确。

【讨论】:

    【解决方案3】:

    它也可以在 CPU 寄存器中。 C/C++ 关键字“register”告诉 CPU 将变量保存在寄存器中,但您不能保证它会保留甚至永远不会进入其中。

    【讨论】:

    • C/C++ 关键字“register”建议 编译器 应该将变量保存在寄存器中!!!
    • 如果你拿了一个地址,它就不能再在寄存器里了。
    【解决方案4】:

    只要 Cache/RAM/Harddisk/SSD 不忙于服务其他访问(例如 DMA 请求)并且硬件相当可靠,那么成本仍然是恒定的(尽管它们可能是一个很大的常数)。

    当你得到一个缓存未命中,你必须分页到硬盘读取变量,那么它只是一个简单的硬盘读取请求,这个成本是巨大的,因为CPU必须:发送中断到内核进行硬盘读取请求,向硬盘发送请求,等待硬盘将数据写入 RAM,然后将数据从 RAM 读取到缓存和寄存器。但是,这个成本仍然是不变的成本。

    实际数字和比例会因您的硬件和硬件的兼容性而异(例如,如果您的 CPU 以 2000 Mhz 运行,而您的 RAM 以 333 Mhz 发送数据,那么它们的同步性并不好)。解决这个问题的唯一方法是在您的程序中对其进行测试。

    这不是过早的优化,这是微优化。让编译器担心这些细节。

    【讨论】:

    • 次优内存访问模式不是编译器可以为您解决的问题。您需要编写代码,以便以最佳方式访问内存。如果您完全关心结果的性能,这不是过早的优化!一开始就不要做错事,这只是为自己节省了一些时间。 (此外,缓存未命中与硬盘无关。)
    • 是的,这不是过早的优化;这是微优化。并且它编译器(和 CPU)的工作来重新排列指令以最小化缓存未命中(和页面未命中)。
    • 但是当你编写二叉树时,编译 B 树并不是编译器的工作。编译器不是你可以洒在代码上以使其快速运行的魔法小精灵。
    • 大多数优化编译器,在某种程度上,CPU 已经这样做了(重新排列指令以获得最佳内存访问模式)。重新排列字节码/汇编指令是一个机械过程,这就是编译器/CPU可以做到这一点的原因。只需选择一个好的算法和一个好的数据结构,然后让编译器(和 CPU)来做这种微优化。 (有些内存访问优化不是微优化,特别是对于大型数组,选择缓存友好的算法有很大帮助;但在所呈现的情况下,它是微优化)
    【解决方案5】:

    这些数字一直在变化。但对于 2010 年的粗略估计,Kathryn McKinley has nice slides on the web,我不觉得有必要在此复制。

    您要的搜索词是“内存层次结构”或“内存层次结构成本”。

    【讨论】:

      【解决方案6】:

      我还能去哪里?

      i*i 是不同的东西,它们都可以位于列表中的任何位置。进行分配时,指针地址可能还存储在 CPU 寄存器中,因此不需要从 RAM/Cache/...

      关于性能:这高度依赖于 CPU。从数量级来看,访问 RAM 比访问缓存条目更糟糕,访问换出的页面是最糟糕的。所有这些都有些不可预测,因为它们也取决于其他因素(即其他处理器,取决于系统架构)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-15
        • 2016-08-11
        • 1970-01-01
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        相关资源
        最近更新 更多