有没有一种完全避免缓存未命中的方法?

6
我在这里阅读了关于缓存如何工作的基础知识:如何以及何时对齐缓存行大小?什么是“缓存友好”代码?,但是这些帖子都没有回答我的问题:有没有一种方法可以完全在缓存中执行一些代码,即不使用任何访问RAM的方式(除了可能在从HDD读取文件的初始过程中)?据我所知,计算机运算瓶颈现在主要是内存带宽,“只要你在CPU内部,就没问题”。
是否有一种方法将程序加载到缓存中,并将其保留在那里直到终止?因此,假设我有一个1MB编译后的C程序,它需要另外1MB的内存进行一些科学计算,并运行5天。是否有一种方法标记此代码,以便在评估期间不会从缓存中退出?我考虑在执行期间为此代码提供更高的优先级等。
换句话说,闲置计算机使用多少缓存,它加载其操作系统(比如Ubuntu),然后什么也不做?在空闲期间是否存在过度使用缓存?如果操作系统除了执行该程序外什么也不做,我应该期望我的小程序始终在缓存中吗?比如5分钟后启动屏幕保护程序。这是否会导致大量的缓存未命中(因此,性能急剧下降),因为现在它与我的程序竞争缓存空间?我的经验表明,同时运行几个不要求太高的程序(如屏幕保护程序、简单的音频播放器、pdf阅读器等)并不会显著降低科学计算程序的性能,尽管我本来希望它会一直进出缓存。问题是:为什么它的速度没有受到影响?使用绝对最小化的操作系统(如果是这样,那么是哪一个?)来提高计算速度有意义吗?
只是为了澄清,我们可以假设代码非常简单,比如一堆嵌套的for循环,其中最内部的部分将所有增量变量模97相加。关键是它足够小,可以放置和执行在缓存中。
5个回答

6

不同类型的CPU缓存未命中:强制性、冲突、容量和一致性。

无法避免必要未命中,因为当内存位置首次被引用时,它们就会发生。所以,你绝对不能完全避免缓存未命中。

此外,如今典型的L1缓存大小为每个核心32KB / 64KB,而L2缓存大小为每个核心256KB。因此,1MB的数据也会创建容量或冲突未命中,具体取决于缓存的关联性。


有趣的链接;我从未听说过这种分类。我现在看到最近的Xeon每个核心都有256kb的L2缓存,而旧型号则使用1-3MB。现在似乎较小的L2但更大的L3是“趋势”。谢谢。 - Matsmath
强制缺失可以通过预取来隐藏,可以在硬件或软件中执行。导致从内存加载数据到高速缓存的指令不会停顿在结果内存总线事务上。当然,这引起了两个问题,即这些是否为高速缓存缺失:语义上,无论讨论高速缓存缺失的目的是什么;机械上,给定的CPU微架构是否会增加相关的性能计数器。根据设计师通常在计数器上提供的非常有限的程度,CPU可能会有所不同。 - Phil Miller

3
不,在大多数标准架构中,CPU缓存无法寻址。*

而且即使你能够这样做,你期望的性能提升是什么?你认为有多少百分比的程序执行时间是用于从主内存加载到(L3)缓存中的?你应该对程序进行剖析以确定它实际上花费了多少时间,而不是想出不存在问题的解决方案!


* 我认为x86 CPU 可能有一种硬件配置,可以在没有连接的RAM的情况下运行,但那基本上是无关紧要的。


如果你说从主存加载程序到L3缓存所需的时间与执行程序本身相比微不足道,那么我恐怕是误解了重点。如果你的第一句话是正确的,那么我不明白缓存未命中是如何成为问题的。关于你的第二条评论:程序非常简单,所以我担心在这种情况下分析并不能帮助解决问题。 - Matsmath
@Matsmath:这实际上就是重点。在某些情况下,负载确实是微不足道的,因为程序大部分时间都在做其他事情。在其他情况下,程序可能会在非常大的工作集中挣扎,此时主存负载肯定是显著的。猜猜你的例子属于哪一类!(是的,你仍然可以使用硬件性能计数器进行分析)。 - Oliver Charlesworth
这一切都很有道理。所以我真正想要的答案是“只要程序足够简单,可以假设它(几乎)总是在缓存中,因为从 RAM 加载它是瞬间完成的。因此,没有必要使用任何高级的方式将其永久保存在缓存中。” 这正是我一直在寻找的。我会尝试将其作为(简短但令人信服的)答案接受。谢谢! - Matsmath
我理解的是,当将堆栈设置在RAM上时,处理器会将堆栈RAM数据提取到L1缓存中并与之一起工作。但是,当将堆栈设置在TCM上时,数据将始终保留在TCM上(没有从TCM提取到L1缓存),因此运行程序时将始终少出现缓存未命中?还是我误解了? - bouqbouq

2

简短回答:不行。缓存由操作系统/CPU维护,允许程序强制自身留在缓存中是一个坏主意。假设您同时运行两个程序,并且两者都试图强制留在缓存中,那么混乱会发生,不是吗?


这是一个很好的观点,当然。这就是为什么我建议将代码的某些部分“优先考虑”而不是其他部分。 - Matsmath
@Matsmath 无论如何,CPU制造商/操作系统都不会让你这样做。因此,答案是否定的。 - Steve

2
较新的英特尔CPU在其“资源主管技术”(Resource Director Technology)的总体范畴下增加了“缓存分配技术”(Cache Allocation Technology,CAT)。这使得软件指令可以为特定的计算单元(应用程序、容器、虚拟机等)保留某些缓存(和其他)资源。因此,如果所涉及的进程在CAT下有足够的缓存空间,它应该只会遇到初始强制缺失(将其代码和数据带入缓存)和自身引起的冲突缺失,避免了由其他进程创建的容量缺失和冲突缺失。

1
看起来英特尔对我的问题产生了兴趣 :-). - Matsmath

1
我不确定它是否能满足你的问题。
有没有一种方法可以完全在缓存中执行代码,即不使用任何访问RAM的方式? 有没有一种方法可以将程序加载到缓存中,并使其保留在那里直到终止?
可以使用完全关联的高速缓存(例如紧密耦合的内存),其具有单周期访问时间。(这只在非常小的嵌入式系统中才是现实的。)在嵌入式系统中使用TCM来进行时间关键代码是一种通用做法,因为它提供可预测性。
在部分关联缓存的情况下,可以锁定缓存行或路(例如使用ARM中的CP15),以便驱逐算法不将其视为缓存填充的受害者。
顺便说一下,有时将缓存用作RAM对于调试模式下的非启动板的调试也很有用。 (http://www.asset-intertech.com/Products/Processor-Controlled-Test/PCT-Software/Cache-as-RAM-for-board-bring-up-of-non-boothing-ci

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