确定CPU高速缓存中值的值和/或地址

时间:2013-01-16 22:22:35

标签: c++ c windows memory-management cpu-cache

有没有办法确定当前或所有进程中当前驻留在CPU缓存(L1,L2等)中的值,内存地址和/或其他信息?

我一直在做一些阅读,它展示了如何优化程序以更有效地利用CPU缓存。但是,我正在寻找一种方法来真正确定某些方法是否有效。

底线:是否可以 100%确定什么做到和不做进入CPU缓存。

搜索此主题将返回有关如何确定缓存大小的若干结果,但不会返回内容。

编辑:为了澄清下面的一些评论:由于软件无疑会改变缓存,CPU制造商是否拥有提供此功能的工具/硬件诊断系统(内置)? p>

5 个答案:

答案 0 :(得分:3)

如果不使用专用硬件,则无法直接检查CPU缓存中的内容。运行任何软件来检查CPU缓存的行为都会改变缓存的状态。

我发现的最佳方法是识别应用程序中的真正热点,并在代码将在生产中运行的硬件上对替代算法进行基准测试(如果您无法控制生产环境,则可以在一系列可能的硬件上运行)。

答案 1 :(得分:2)

除了Eric J.的答案之外,我还要补充一点,虽然我确信大芯片制造商确实拥有这样的工具,但是这样的“调试”设施不太可能提供给像你这样的普通人。我,但即使它是,它也不会真的有很多帮助。

为什么呢?您不太可能遇到已经跟踪到缓存的性能问题,而且使用众所周知的“常识”技术来维持高缓存命中率无法解决这些问题。

您是否真正优化了代码中的所有其他热点,并且CPU的缓存行为不佳是问题所在?我非常怀疑。

此外,作为深思熟虑:您真的想要将程序的行为优化为仅一个或两个特定的CPU吗?毕竟,缓存算法一直在变化,缓存的参数也是如此,有时会非常显着。

答案 2 :(得分:1)

如果您有一个运行Windows的相对现代的处理器,那么请看一下 http://software.intel.com/en-us/articles/intel-performance-counter-monitor-a-better-way-to-measure-cpu-utilization 并查看是否可能提供您正在寻找的一些内容。

答案 3 :(得分:1)

为一个特定的CPU缓存大小进行优化通常是徒劳的,因为当您在不同的CPU上执行时,当您对CPU缓存大小的假设错误时,此优化将会中断。

但是有一条出路。您应优化某些访问模式,以便CPU能够轻松预测下一步应读取的内存位置(最明显的是线性增加读取)。为了能够充分利用CPU,您应该阅读cache oblivious算法,其中大多数算法遵循分而治之的策略,将问题分成若干子部分到一定程度,直到所有内存访问完全适合CPU缓存。

值得一提的是,您有一个独立的代码和数据缓存。 Herb Sutter有一个很好的video在线,他深入讨论了CPU的内部结构。

Visual Studio Profiler可以收集处理内存和L2计数器的CPU计数器。选择检测分析时,可以使用这些选项。

英特尔还有一个关于这些CPU计数器的更详细的paper online which会谈,以及Windows和Linux的任务管理器向您展示的内容以及当前在内部异步和并行工作的CPU有多么不同之处水平。 Unfortunatley没有英特尔的工具直接显示这些东西。我所知道的唯一工具是VS分析器。也许VTune有类似的能力。

如果你已经走了这么远来优化你的代码,你可能会看到GPU编程。你需要至少一个PHD才能了解SIMD指令,缓存局部性......,或许比原始设计要好5倍。但是通过将您的算法移植到GPU,您可以获得100倍的效果,而不需要花费太多精力。支持CUDA的NVidia GPU(所有今天售出的卡都支持它)可以用C语言编写得非常好。甚至还有托管代码(.NET)的包装器来利用GPU的全部功能。

您可以使用OpenCL保持平台无关,但NVidia OpenCL支持非常糟糕。 OpenCL驱动程序至少比其CUDA驱动程序慢8倍。

答案 4 :(得分:1)

除非您正在读取已配置为“不可缓存”的内存(通常是图形卡的帧缓冲内存),否则您使用它时几乎所有操作都将在缓存中。 “未点击缓存”的另一种方法是使用“非时间”的特定加载和存储指令。在其到达CPU本身内的目标寄存器之前,其他所有内容都被读入L1高速缓存。

对于几乎所有情况,CPU都有一个相当不错的系统,知道要保留什么以及在缓存中丢弃什么,并且缓存几乎总是“满” - 不一定是有用的东西,例如,如果你正在通过一个庞大的数组工作,它将包含许多“旧数组”[这是“非时间”内存操作派上用场的地方,因为它们允许您读取和/或写入赢得的数据' t存储在缓存中,因为下次返回到同一点时,它将不会在缓存中[ANYWAYS]。

是的,处理器通常有特殊的寄存器[可以在内核驱动程序中访问],可以检查缓存的内容。但是它们使用起来非常棘手,同时又不会丢失缓存的内容。并且它们绝对没有用作“数组A在缓存中有多少”类型检查。它们专门用于“嗯,看起来高速缓存行1234坏了,我最好读取缓存数据,以确定当处理器不能正常工作时它是否真的应该是它的价值”。

正如DanS所说,有些性能计数器可以从合适的软件中读取[需要在内核中使用这些寄存器,所以你需要某种“驱动”软件]。在Linux中,有“perf”。 AMD有一组类似的性能计数器,可用于查找,例如“我们在这段时间内有多少缓存未命中”或“L中有多少缓存命中”,等等。