假设我的数组是32KB,L1是64 KB。 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也一样。
还有功能保存在缓存中吗?缓存是只读的吗? (如果我更改了我的数组,那么它会丢失缓存绑定?)
编译器是否创建了asm代码以使用缓存更多的收益?
由于
答案 0 :(得分:14)
我怎么知道我的数组在缓存中?
一般情况下,你不能。一般来说,缓存由硬件直接管理,而不是由Windows管理。您也无法控制数据是否驻留在缓存中(尽管可以指定不应缓存内存区域)。
Windows在程序运行时是否使用了部分内容?也许我无法使用L1,因为Windows正在使其他程序工作?我应该将程序的优先级设置为使用所有缓存吗?
L1和L2缓存由在给定核心上运行的所有进程共享。当您的进程正在运行时,它将使用所有缓存(如果需要)。当有上下文切换时,部分或全部高速缓存将被逐出,具体取决于第二个进程需要什么。因此,下次将上下文切换回您的进程时,可能必须重新填充缓存。
但同样,这一切都是由硬件自动完成的。
还有功能保存在缓存中吗?
在大多数现代处理器上,有一个单独的缓存用于指令。参见例如this diagram显示了英特尔Nehalem架构的安排;注意共享的L2和L3缓存,但是单独的L1缓存用于指令和数据。
缓存是只读的吗?(如果我更改了我的数组,那么它会丢失缓存绑定吗?)
没有。缓存可以处理修改后的数据,但这要复杂得多(因为the problem of synchronising multiple caches in a multi-core system。)
编译器是否创建了asm代码以使用缓存更多的收益?
由于缓存活动通常全部由硬件自动处理,因此无需特殊说明。
答案 1 :(得分:1)
缓存不是由操作系统直接控制的,它已完成 在硬件
如果是上下文切换,另一个应用程序可能会修改 缓存,但你不应该关心这个。更重要的是 处理程序表现缓存不友好的情况。
函数保存在缓存中(I-Cahce,指令缓存)
缓存不是只读的,当你写东西时,它会进入[内存 和]缓存。
答案 2 :(得分:1)
据我所知,你无法控制缓存中的内容。您可以将变量声明为register var_type a
,然后访问它将在一个循环(或少量循环)中。此外,访问大块内存所需的周期数也取决于虚拟内存转换和TLB。
应该注意的是,register关键字只是一个建议,编译器可以完全自由地忽略它,正如评论所建议的那样。
答案 3 :(得分:1)
缓存主要由硬件控制。但是,我知道Windows调度程序倾向于将线程的执行安排到与之前相同的核心,因为缓存。它理解有必要将它们重新加载到另一个核心上。 Windows至少从Windows 2000开始就使用此行为。
答案 4 :(得分:1)
正如其他人所说,你通常无法控制缓存中的内容。如果您正在编写高性能代码并且需要依赖缓存来提高性能,那么编写代码并使用大约一半的L1缓存空间并不罕见。这样做的方法涉及超出StackOverflow问题范围的大量讨论。从本质上讲,您希望在转移到其他数据之前对某些数据执行尽可能多的工作。
实际上,使用大约一半的缓存会留下足够的空间来发生其他事情,大多数数据都会保留在缓存中。如果没有来自操作系统和计算平台的其他方面的合作,您不能依赖于此,因此它可能是加速研究计算的有用技术,但它不能用于必须保证实时性能的地方,如操作危险机械
除了您使用的数据量之外,还有其他警告。使用映射到相同缓存行的数据可以从缓存中逐出数据,即使有大量缓存未使用。矩阵转置因此而臭名昭着,因为行长度为2的中等幂的倍数的矩阵将具有列,其中元素映射到一小组缓存行。因此,学习有效地使用缓存是一项重要工作。
答案 5 :(得分:1)
即使你可能不知道哪些数据在缓存中,哪些数据不在缓存中,你仍然可以知道你正在使用多少缓存。现代处理器有很多性能计数器,其中一些与缓存有关。英特尔的处理器可能会告诉您有多少L1和L2未命中。请查看此处了解有关如何执行此操作的详细信息:How to read performance counters on i5, i7 CPUs