new / malloc或delete / free是否占用或使缓存行无效?

时间:2015-06-24 09:48:53

标签: c++ c caching

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

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

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

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

  4. 有人能给我一个提示吗?

3 个答案:

答案 0 :(得分:3)

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

-

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

来自文章:

  

默认情况下,CPU内核读取或写入的所有数据都存储在   缓存。存在无法缓存的内存区域,但这是   只有OS实施者必须关注的事情;它是   应用程序员看不到。还有说明   这允许程序员故意绕过某些缓存。这个   将在第6节中讨论。

-

  
      
  1. 分配大容量内存时,内存可能来自操作系统。这个机制会占用缓存吗?
  2.   

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

  

在具有请求分页支持的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之后,所有权从您的程序传输到运行时或操作系统。