【问题标题】:Does new/malloc or delete/free occupy or invalidate cache lines?new/malloc 或 delete/free 是否占用或使缓存行无效?
【发布时间】:2015-06-24 09:48:53
【问题描述】:

我对缓存行为很好奇。下面是一些与缓存相关的问题:

  1. 写操作是否将数据带入缓存? 考虑像 A[i] = B[i] 这样的赋值,A[i] 会被加载到缓存中吗?因为我只是在 A[i] 中写入一些东西而不是读取它的值。

  2. 分配大内存时,内存可能来自操作系统。出于安全原因,操作系统会将数据初始化为零(Reference)。如果赋值会将数据带入缓存(问题一),这种机制会不会占用缓存?

  3. 假设有一个分配的数组B,现在整个B都在缓存中。在我释放数组 B 后,被 B 占用的缓存行会变得无效(可用)吗?

有人可以给我一个提示吗?

【问题讨论】:

  • 我会说这不是语言可以控制的。对于语言来说,所有这些都被抽象为“记忆”。请参阅this
  • @ArjunSreedharan:编译器确实知道操作系统和 CPU。它可能会添加缓存控制指令。

标签: c++ c caching


【解决方案1】:

从这里https://people.freebsd.org/~lstewart/articles/cpumemory.pdf

--

  1. 写操作是否将数据带入缓存?

来自文章:

默认情况下,CPU 内核读取或写入的所有数据都存储在 缓存。有些内存区域无法缓存,但这是 只有操作系统实现者才需要关心的事情;它是 应用程序程序员不可见。还有说明 这允许程序员故意绕过某些缓存。这 将在第 6 节中讨论。

--

  1. 分配大内存时,内存可能来自操作系统。这种机制会不会占用缓存?

可能不会。只有在读取或写入数据后才会占用缓存。来自文章:

在支持按需分页的 Linux 等操作系统上,mmap 调用只修改页表...没有分配实际内存 在调用 mmap 时。

分配部分发生在第一次访问内存页面时, 通过读取或写入数据,或通过执行代码。作为回应 对于随后的页面错误,内核控制并确定, 使用页表树,必须存在的数据 页。页面错误的这种解决方法并不便宜,但它确实发生了 对于进程使用的每个页面。

--

3 .假设有一个分配的数组B,并且整个B现在都在缓存中。在我释放数组 B 之后,被 B 占用的缓存行会变得无效(可用)吗?

来自文章的缓存行失效仅在另一个 CPU 上发生写操作时发生

多年来开发的是 MESI 缓存一致性协议 (修改、独占、共享、无效)。该协议以 使用 MESI 协议时缓存行可以处于的四种状态。 ...如果第二个处理器想要写入第一个缓存行 处理器发送缓存行内容并标记缓存行 本地为无效。

缓存行也可以被驱逐:

缓存的另一个细节是相当无趣的 程序员是缓存替换策略。大多数缓存驱逐 最近最少使用 (LRU) 元素优先。

根据我对 TCMalloc 的经验,free() 并不是从缓存中驱逐内存的令人信服的理由。相反,它可能对性能有害。在free() TCMalloc 上只是将一个已释放的内存块放入其缓存中。当应用程序下次请求内存块时,malloc() 将返回这块内存。这就是像 TCMalloc 这样的缓存分配器的本质。如果这块内存还在缓存中,那么性能会更好!

【讨论】:

  • 除了 3):理论上,free/delete 可以显式发出缓存失效指令/请求 - 不过我从未见过任何实现这样做。
【解决方案2】:

这是一篇有趣的文章,您会在其中找到有关您所询问内容的更多信息(可能太多):

What every programmer should know about memory

关于您的问题,您对内存执行的每项操作都将被缓存。作为程序员,您无法控制它(而前夕操作系统没有)。请记住,如果您需要实现空间(内存)消耗算法,请尝试增加内存局部性。

因此,假设您必须处理 1GB 的数据,请尝试将计算拆分为集群(数据部分)并尝试一次执行所有操作。这样,您实际上将使用缓存中的数据,而无需每次都访问外部内存。这可能会给您带来性能提升。

【讨论】:

  • 实际上操作系统对缓存有很大的控制权,而且必然如此。如果 CPU 缓存包含来自先前运行的进程的剩余数据,那将是非常糟糕的。而且由于 CPU 不知道进程,这必须是操作系统强制执行的。
【解决方案3】:

要回答标题问题,不。这些操作不会使缓存无效,而且是故意的。释放的内存会发生什么?有两个重要的案例。一,内存会立即为您的程序下一次分配而回收。在这种情况下,将地址仍在缓存中是有效的,因为这减少了对主内存的写入次数。

但是即使内存没有被直接重用,内存分配器也可能在后台合并空闲块或执行其他操作。这通常涉及写入数据之前分配的空间。毕竟,释放内存并不会在物理上破坏内存。它只是设置所有者。在delete 之后,所有权从您的程序转移到运行时或操作系统。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多