1

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

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

底线:是否有可能100% 确定哪些可以进入 CPU 缓存,哪些不能进入 CPU 缓存。

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

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

4

5 回答 5

3

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

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

于 2013-01-16T22:27:21.137 回答
2

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

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

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

此外,值得深思的是:您真的想将程序的行为优化到只针对一个或两个特定的 CPU 吗?毕竟,缓存算法一直在变化,缓存的参数也是如此,有时会发生巨大变化。

于 2013-01-16T22:39:01.097 回答
1

如果您有一个运行 Windows 的相对现代的处理器,请查看 http://software.intel.com/en-us/articles/intel-performance-counter-monitor-a-better-way-to-measure-cpu-利用率 ,看看这是否可以提供您正在寻找的一些东西。

于 2013-01-16T22:53:39.763 回答
1

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

但有一条出路。您应该针对某些访问模式进行优化,以允许 CPU 轻松预测接下来应该读取哪些内存位置(最明显的是线性递增读取)。为了能够充分利用 CPU,您应该阅读有关缓存遗忘算法的内容,其中大多数算法遵循分而治之的策略,其中问题在一定程度上被划分为子部分,直到所有内存访问完全适合 CPU 缓存。

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

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

英特尔还有一篇在线论文,其中更详细地讨论了这些 CPU 计数器以及 Windows 和 Linux 的任务管理器向您展示的内容,以及对于当今在许多不同级别上内部异步和并行工作的 CPU 来说这是多么错误。不幸的是,英特尔没有工具可以直接显示这些东西。我知道的唯一工具是 VS 分析器。也许 VTune 也有类似的能力。

如果您已经走到这一步来优化您的代码,那么您也可以研究一下 GPU 编程。您至少需要一个 PHD 来了解 SIMD 指令、缓存位置等,以使您的原始设计可能达到 5 倍。但是通过将你的算法移植到 GPU 上,你可以在一张像样的显卡上花费更少的精力来获得 100 倍的收益。支持CUDA的 NVidia GPU (现在所有出售的显卡都支持它)可以用 C 语言很好地编程。甚至还有托管代码 (.NET) 的包装器来利用 GPU 的全部功能。

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

于 2013-01-16T23:24:03.887 回答
1

Almost everything you do will be in the cache at the moment when you use it, unless you are reading memory that has been configured as "uncacheable" - typically, that's frame buffer memory of your graphics card. The other way to "not hit the cache" is to use specific load and store instructions that are "non-temporal". Everything else is read into the L1 cache before it reaches the target registers inside the CPU itself.

For nearly all cases, CPU's do have a fairly good system of knowing what to keep and what to throw away in the cache, and the cache is nearly always "full" - not necessarily of useful stuff, if, for example you are working your way through an enormous array, it will just contain a lot of "old array" [this is where the "non-temporal" memory operations come in handy, as they allow you to read and/or write data that won't be stored in the cache, since next time you get back to the same point, it won't be in the cache ANYWAYS].

And yes, processors usually have special registers [that can be accessed in kernel drivers] that can inspect the contents of the cache. But they are quite tricky to use without at the same time losing the content of the cache(s). And they are definitely not useful as "how much of array A is in the cache" type checking. They are specifically for "Hmm, it looks like cache-line 1234 is broken, I'd better read the cached data to see if it's really the value it should be" when processors aren't working as they should.

As DanS says, there are performance counters that you can read from suitable software [need to be in the kernel to use those registers too, so you need some sort of "driver" software for that]. In Linux, there's "perf". And AMD has a similar set of performance counters that can be used to find out, for example "how many cache misses have we had over this period of time" or "how many cache hits in L" have we had, etc.

于 2013-01-16T23:25:10.767 回答