如何判断我的数组是否在缓存中?

3
假设我的数组大小为32KB,L1缓存大小为64KB。在程序运行时,Windows会使用其中一部分吗?也许我无法使用L1缓存是因为Windows正在使其他程序工作?我应该设置我的程序优先级以使用所有缓存吗?
for(int i=0;i<8192;i++)
{
  array_3[i]+=clock()*(rand()%256);//clock() and rand in cache too?
  //how many times do I need to use a variable to make it stay in cache?
  //or cache is only for reading? look below plz
  temp_a+=array_x[i]*my_function();
}

这个程序使用C/C++编写。

同样的事情也适用于L2。

函数是否被保存在缓存中?缓存是只读的吗?(如果我更改我的数组,那么它就会失去缓存绑定关系吗?)

编译器是否创建汇编代码以更多地利用缓存?

谢谢。


3
你无法知道你的数组是否在缓存中,除非尝试读取内存位置。我无法为你提供更多信息。 - Mysticial
我相信缓存是由您的处理器处理的,最近访问的内存通常会在缓存中,与此相邻的内存地址(例如数组中的元素)也会在缓存中。 - Sam I am says Reinstate Monica
好的。谢谢。我得到了我的答案。 - huseyin tugrul buyukisik
6个回答

14

如何知道我的数组是否在缓存中?

通常情况下,你无法知道。一般来说,缓存是由硬件直接管理的,而不是由Windows管理。你也无法控制数据是否驻留在缓存中(尽管有可能指定一个内存区域不应该被缓存)。

程序运行时,Windows会使用其中一些吗?也许我不能使用L1缓存,因为Windows正在让其他程序工作?我应该设置我的程序优先级以使用所有缓存吗?

L1和L2缓存由在给定核心上运行的所有进程共享。当你的进程正在运行时,它将使用所有缓存(如果需要)。当发生上下文切换时,一些或所有缓存将被清除,这取决于第二个进程的需求。所以下次再切换回你的进程时,缓存可能需要重新填充。

但同样地,这一切都是由硬件自动完成的。

函数也会保留在缓存中吗?

在大多数现代处理器上,指令有一个单独的缓存。例如,参见此图表,它显示了Intel Nehalem架构的排列方式;请注意共享的L2和L3缓存,但是指令和数据有单独的L1缓存。

缓存是只读的吗?(如果我更改我的数组,那么它会失去缓存绑定吗?)

不是。缓存可以处理修改后的数据,尽管这会更加复杂(因为在多核系统中同步多个缓存的问题)。

编译器是否创建汇编代码以更有效地使用缓存?

由于缓存活动通常都由硬件自动处理,因此不需要特殊指令。

1
  • 缓存不是由操作系统直接控制的,而是在硬件中完成的。

  • 在上下文切换的情况下,另一个应用程序可能会修改缓存,但您不需要关心这个问题。更重要的是处理程序表现出缓存不友好的情况。

  • 函数被保存在缓存中(I-Cache,指令缓存)。

  • 缓存不是只读的,当您写入某些内容时,它会进入[内存和]缓存。


1
据我所知,您无法控制缓存中会有什么。您可以将变量声明为register var_type a,然后对其进行访问将在单个周期(或少量周期)内完成。此外,访问一块内存所需的周期数还取决于虚拟内存转换和TLB。
需要注意的是,寄存器关键字只是一个建议,编译器完全可以忽略它,正如评论所建议的那样。

1
没有冲突的可能性,因为寄存器关键字只是一个建议,编译器完全可以忽略它。 - Benjamin Lindley
@Benjamin Lindle 谢谢你。我在学校里被教过它的含义,并普遍避免使用。我会编辑这个回答。 - Digital Da
使用“register”声明变量对于现代编译器几乎没有任何意义,也不能保证该变量将被保存在寄存器中。此外,即使在寄存器中,也不能保证对它的访问只需要一个时钟周期。(例如,在某些处理器上,从矢量单元寄存器移动数据到标量单元寄存器需要多个时钟周期。) - Eric Postpischil

1
缓存主要由硬件控制。然而,我知道Windows调度程序倾向于将线程的执行安排到与之前相同的核心上,特别是因为缓存。它理解在另一个核心上重新加载它们将是必要的。自Windows 2000以来,Windows一直在使用这种行为。

1

正如其他人所说,通常情况下你无法控制缓存中的内容。如果你正在编写高性能代码并需要依赖缓存来提高性能,那么通常会编写代码,使其使用 L1 缓存空间的一半左右。这样做的方法涉及到很多讨论,超出了 StackOverflow 问题的范围。基本上,在移动到其他数据之前,你希望尽可能多地处理某些数据。

就实际可行性而言,使用大约一半的缓存留出足够的空间供其他事情发生,这样大部分数据都将保留在缓存中。但是,你不能指望在没有操作系统和计算平台的合作下实现这一点,因此它可能是加速研究计算的有用技术,但不能用于必须保证实时性能的操作危险机器等场景。

除了使用多少数据之外,还有其他注意事项。即使有大量未使用的缓存,使用映射到相同缓存行的数据也可能会将数据从缓存中驱逐出去。矩阵转置以此著称,因为行长度是中等二次幂的倍数的矩阵将具有列,其中元素映射到一小组缓存行。因此,学习有效地使用缓存是一项重要的工作。


1

即使您可能不知道哪些数据在缓存中,哪些不在,您仍然可以了解您正在利用多少缓存。现代处理器有很多性能计数器,其中一些与缓存有关。Intel的处理器可以告诉您有多少个L1和L2缺失。查看此处以获取更多详情:如何读取i5、i7 CPU上的性能计数器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接