新的/malloc或删除/free占用或使缓存行无效

Does new/malloc or delete/free occupy or invalidate cache lines?

本文关键字:缓存 无效 free malloc 删除 新的      更新时间:2023-10-16

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

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

  2. 当分配大内存时,内存可能来自操作系统。出于安全考虑,操作系统会将数据初始化为零(参考)。如果分配会将数据带入缓存(问题1),这种机制会占用缓存吗?

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

有人能给我一个提示吗?

从这里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这样的缓存allocator的本质。如果这个内存块仍然在缓存中,那么它的性能会更好!

这是一篇有趣的文章,你会发现更多关于你所问内容的信息(可能太多了):

每个程序员都应该了解内存

关于你的问题,你在内存上做的每一个操作都会被缓存。作为一名程序员,你对它没有任何控制权(即使操作系统也没有)。请记住,如果您需要实现一个占用空间(内存)的算法,那么请尝试增加内存的局部性。

因此,假设您必须处理1GB的数据,请尝试将计算拆分为集群(数据段),并尝试一次一段地执行所有操作。通过这种方式,您将实际使用缓存中的数据,而不需要每次都访问外部内存。这可能会提高您的性能。

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

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