我很好奇缓存行为。以下是与缓存相关的一些问题:
写入操作是否将数据带入缓存? 考虑像A [i] = B [i]这样的赋值,A [i]会被加载到缓存中吗?因为我只是在A [i]中写东西而不是读取它的值。
分配大内存时,内存可能来自操作系统。并且出于安全原因(OS Reference),操作系统会将数据初始化为零。如果赋值将数据带入缓存(问题1),此机制是否会占用缓存?
假设有一个已分配的数组B,整个B现在都在缓存中。在我释放数组B之后,B占用的缓存行是否会变为无效(可用)?
有人能给我一个提示吗?
答案 0 :(得分:3)
从这里https://people.freebsd.org/~lstewart/articles/cpumemory.pdf
-
- 写入操作是否将数据带入缓存?
醇>
来自文章:
默认情况下,CPU内核读取或写入的所有数据都存储在 缓存。存在无法缓存的内存区域,但这是 只有OS实施者必须关注的事情;它是 应用程序员看不到。还有说明 这允许程序员故意绕过某些缓存。这个 将在第6节中讨论。
-
- 分配大容量内存时,内存可能来自操作系统。这个机制会占用缓存吗?
醇>
可能不是。只有在读取或写入数据后才会占用缓存。来自文章:
在具有请求分页支持的Linux等操作系统上,使用mmap call仅修改页表...没有分配实际内存 在mmap调用时。
分配部分在首次访问内存页时发生, 通过读取或写入数据,或通过执行代码。作为回应 对于随后的页面错误,内核控制并确定, 使用页表树,必须存在的数据 页。这种页面错误的解决方案并不便宜,但它确实发生了 对于流程使用的每个页面。
-
3.假设有一个已分配的数组B,整个B现在都在缓存中。在我释放数组B后,B占用的缓存行是否会变为无效(可用)?
来自文章的高速缓存行失效只有在另一个CPU上有写操作时才会发生
多年来开发的是MESI缓存一致性协议 (已修改,独占,共享,无效)。该协议以其命名 使用MESI协议时,缓存行可以处于四种状态。 ...如果第二个处理器想要先写入缓存行 处理器发送缓存行内容并标记缓存行 本地无效。
并且还可以逐出缓存行:
缓存的另一个细节是相当无趣的 程序员是缓存替换策略。大多数缓存都会逐出 最近最少使用(LRU)元素。
根据我对TCMalloc free()
的经验,并不是从缓存中驱逐内存的令人信服的理由。相反,它可能对性能有害。在free()
TCMalloc只是在其缓存中放置一个释放的内存块。当应用程序下次请求内存块时,malloc()
将返回此内存块。这就是像TCMalloc这样的缓存分配器的本质。如果这块内存仍然在缓存中,那么性能会更好!
答案 1 :(得分:2)
这是一篇有趣的文章,你会发现有关你所询问的更多信息(可能太多):
What every programmer should know about memory
关于您的问题,您在内存上执行的每项操作都将被缓存。作为程序员,你无法控制它(并且操作系统没有)。请记住,如果您需要实现空间(内存)消耗算法,请尝试增加内存位置。
因此,假设您必须处理1GB数据,请尝试将计算分解为集群(数据部分),并尝试一次执行所有操作。这样,您实际上将使用缓存中的数据,而不是每次都需要访问外部内存。这可能会提升您的性能。
答案 2 :(得分:1)
要回答标题问题,不。这些操作不会使缓存失效,而且非常有意。释放内存会发生什么?有两个重要的案例。一,内存会立即为您的程序下次分配回收。在这种情况下,将地址保留在高速缓存中是有效的,因为这会减少对主存储器的写入次数。
但即使没有直接重用内存,内存分配器也可能在后台合并空闲块或执行其他操作。这通常涉及写入以前由数据分配的空间。毕竟,释放内存并不会破坏内存。它只是设置所有者。在delete
之后,所有权从您的程序传输到运行时或操作系统。