优化CPU缓存(在C中)时重要的是什么?


13

阅读两个问题,我发现了解CPU缓存行为在处理内存中的大量数据时可能很重要。我想了解缓存的工作方式,以便将其他工具添加到优化工具箱中。

关于CPU缓存工作方式的核心点是什么,以便我可以编写明智地使用它的代码?相关地,是否有一种方法可以对代码进行概要分析,以查看缓存使用不当是否会减慢速度?


各地的缓存都不尽相同。最明显的是,它们的大小各不相同。不要指望学习任何深奥的秘密,而要学习良好的做法(例如迈克尔·伯格沃德(Michael Borgwardt)的建议)。
David Thornley

Answers:


17
  • 如果可能,使数据保持较小
  • 将将要一起访问(或紧接访问)的内容彼此相邻放置在内存中
  • 了解编译器的优化参数
  • 阅读每个程序员应该了解的内存知识,以获取比您可能想要的更多的详细信息

+1表示“保持将彼此相邻访问的事物”;那就是很容易忘记的那个。
Donal Fellows

并告诉编译器进行优化。
rightfold

@WTP:对-已添加。
Michael Borgwardt

另外,请保持互斥锁的良好分离。更改互斥锁(应该)在所有CPU上刷新它所在的所有缓存行。如果您已设法在单个高速缓存行中获得2-3个互斥锁,那么这可能会严重影响性能。
Vatine 2011年

12

如今,这个问题的复杂性已经超出了人类的理解范围。(自最近5年以来一直是这种方式。)将其与短向量并行性(SIMD)结合使用,您会感到绝望的是,手动优化代码在经济上不再可行-并非不可能,但是这样做不再具有成本效益。

当前的方法是依靠教计算机如何进行优化-通过使代码变体来计算具有不同结构(循环,数据结构,算法)的相同答案并自动评估性能。使用非常严格的数学模型指定了代码转换的规则,因此计算机科学家可以理解并且计算机可以执行。

以下是Larry OBrien在其答案之一中发布的链接。

http://onward-conference.org/2011/images/Pueschel_2011_AutomaticPerformanceProgramming_Onward11.pdf


2
所述的FastTesT BLAS实现(GotoBLAS)使用手工优化代码以确保矩阵乘法最大高速缓存的使用
quant_dev

2

完全有可能了解和优化缓存。首先要了解硬件,然后继续控制系统。您对系统的控制越少,成功的可能性就越小。Linux或Windows运行一堆没有闲置的应用程序/线程。

大多数缓存的属性有些相似,它们使用地址字段的某些部分来查找匹配项,并具有深度(方向)和宽度(缓存线)。一些具有写缓冲区,一些可以配置为在写时通过或绕过高速缓存,等等。

您需要敏锐地意识到所有正在访问该高速缓存的内存事务(某些系统具有独立的指令和数据高速缓存,使任务更加容易)。

如果不仔细管理内存,很容易使缓存变得无用。例如,如果您要处理多个数据块,希望将它们保留在高速缓存中,但它们在内存中的地址是相对于高速缓存命中/未命中检查的偶数倍,例如0x10000 0x20000 0x30000,并且您拥有更多这些比缓存中的方式要快得多,您可能很快就会使某些东西在打开缓存时运行得非常慢,比关闭缓存时运行得慢。但是将其更改为0x10000、0x21000、0x32000,可能足以充分利用缓存,从而减少逐出。

最重要的是,优化缓存的关键(嗯,除了非常了解系统之外)是将您需要性能的所有内容同时保留在缓存中,对数据进行整理,以便有可能拥有一次全部放入缓存中。并防止代码执行,中断和其他常规或随机事件之类的东西驱逐出您正在使用的数据的重要部分。

代码也一样。但是,这有点困难,因为您需要控制代码所在的位置,以避免与要保留在缓存中的其他代码发生冲突。在测试/分析通过缓存的任何代码时,会在此四处添加一行代码,甚至添加一个nop,而将同一代码的代码所在地址从一个编译到另一个的更改或更改,都会在以下位置更改或更改:缓存行位于该代码之内,并更改了收回的内容和关键部分没有的内容。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.