【问题标题】:Storing arrays in cache将数组存储在缓存中
【发布时间】:2015-04-10 20:39:18
【问题描述】:

我正在审查一个面试问题并与朋友比较笔记,我们对 CPU 缓存有不同的想法。

考虑一大组数据,比如double的大数组,即:

double data[1024];

考虑使用动态分配的动态链表来存储相同数量的元素。该问题要求描述一些权衡:

  1. 允许更快的随机访问:我们都同意数组更快,因为您不必以线性方式遍历列表 (O(n)),只需提供一个索引 (O(1))。李>
  2. 比较两个相同长度的列表更快:我们都决定如果它只是原始数据类型,则数组将允许memcmp(),而链表需要逐元素比较加上取消引用开销。
  3. 如果您多次访问同一个元素,哪种方式可以提高缓存效率?

3 点,这就是我们意见不同的地方。我争辩说 CPU 会尝试缓存整个数组,如果数组非常大,它就不能存储在缓存中,因此不会有缓存的好处。使用链表,可以缓存单个元素。因此,在处理大量元素时,链表比静态数组更适合缓存“命中”。

对于问题:两者中哪一个更适合缓存“命中”,现代系统可以缓存数组的一部分,还是他们需要整个数组或者它不会尝试?我也可以用来提供明确答案的任何对技术文档或标准的引用都会有很大帮助。

谢谢!

【问题讨论】:

    标签: c arrays performance caching linked-list


    【解决方案1】:

    CPU 不知道您的数据结构。它缓存或多或少的原始内存块。因此,如果您假设您可以多次访问同一个元素而无需每次都遍历列表,那么链表和数组都没有缓存优势。

    但是,在按顺序访问多个元素方面,数组比动态分配的链表有很大的优势。因为 CPU 缓存在内存块上运行,而不是一个double,所以当一个数组元素在缓存中时,很可能其他几个位于相邻地址的元素也在缓存中。因此,从主存储器进行一次(慢速)读取可以访问(快速)缓存访问多个相邻数组元素。链表的情况并非如此,因为节点可以分配在内存中的任何位置,即使是单个节点也至少有next 指针的开销,以稀释可能同时缓存的数据元素的数量。

    【讨论】:

      【解决方案2】:

      缓存不知道数组,它们只是查看内存访问并在该地址附近存储一点内存。一旦您访问了某个地址的某些内容,它应该会在缓存中停留一段时间,无论该地址属于数组还是链表。但是缓存控制器并不真正知道正在访问什么。

      当你遍历一个数组时,缓存系统可能会预取数组的下一位。这通常是启发式驱动的(可能带有一些编译器提示)。

      一些硬件和工具链提供了让您控制缓存驻留的内在函数(通过预取、显式刷新等)。通常你不需要这种控制,但对于像 DSP 代码、资源受限的游戏机和需要担心缓存一致性的操作系统级别的东西,人们使用这种功能是很常见的。

      【讨论】:

      • 我真的不知道他想听什么,但如果我是你的面试官,我可能希望你会说“这个问题没有有效的通用答案”。它取决于机器架构和动态内存实现。理想情况下(动态内存实现中的大缓存和合适的分配块),不会有可测量的差异。然而,将浮点数存储在链表中几乎总是严重浪费资源,并且在大多数情况下没有意义。不要让事情变得过于复杂。
      猜你喜欢
      • 2020-07-26
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2012-01-16
      • 2020-08-29
      相关资源
      最近更新 更多