Mr.*_*son 7 linux performance caching
我正在寻找一个Linux实用程序,它允许在我的程序中分析缓存驱逐.具体来说,我有兴趣找到导致某些缓存行从L2缓存中重复驱逐的原因.
有什么建议?
您可以使用多种选择,其中一些是免费的.下面我将主要讨论分析L2未命中,不一定是L2驱逐,因为这些或多或少是相同的.线路从L2被逐出,因为正在引入另一条线路,并且通常由于L2未命中1而引入另一条线路.
首先,我会试试cachegrind.这基本上在一种轻量级虚拟机下运行你的二进制文件,它允许它拦截所有内存访问,然后模拟它们对缓存的影响.它可以精确查明缓存未命中的位置,负责驱逐的人员等等.
值得注意的是,cachegrind 实际上并没有告诉您硬件缓存发生了什么,而是缓存模型中发生了什么.在Intel x86上,L1和L2仍然很简单,cachegrind模型应该是相当的,除非在特殊情况下准确.
Cachegrind只能模拟两个缓存级别,但现代英特尔有3个或有时4.如果你试图评估L2未命中,那应该不是问题.默认情况下,cachegrind将L1高速缓存设置为本地L1高速缓存的检测值,并将LLC设置为检测到的LLC值.在您的情况下,您将希望覆盖后一个决策以反映L2缓存,而不是LLC.您可以在手册中找到详细信息,但这对于最近的英特尔Broadwell及更早版本应该是正确的:
--LL=262144,8,64
Run Code Online (Sandbox Code Playgroud)
对于Skylake客户/ Kaby Lake和您想要的朋友:
--LL=262144,4,64
Run Code Online (Sandbox Code Playgroud)
对于Skylake-X服务器,您需要查找新值,因为L2已更改.
这种方法的主要缺点是你无法100%确定缓存模型是对现实的准确反映(例如,它不会像预取或虚拟物理分页那样建模).另一个缺点是在cachegrind下运行一个进程可能比原生运行慢一个数量级,但对于"生产"之外的调查,这可能不是问题.
您可以使用默认的,包含的和免费的分析工具来准确了解实际硬件的实际情况:perf.
特别是,您可以perf record结合使用perf report或perf annotate确定程序中未命中的位置.你可以从这样的事情开始:
perf record -e mem_load_retired.l2_miss <your process>
Run Code Online (Sandbox Code Playgroud)
这会定期记录L2未命中的位置.您可以显示结果,perf report以便以交互方式浏览结果.还有很多其他选项,例如--call-graph记录可能有用的完整调用图.
这种perf record方法总是在代码中发生某些事情的地方发生,但它无法帮助您确定未命中时正在访问的内存.这通常无关紧要:代码中的位置通常使得访问内存非常明显.然而,有时情况并非如此:您有一些代码可能会访问大量内存区域,并且您想知道地址以确定错误发生的原因.
在这种情况下,您可以使用perf mem哪些记录未命中代码中的位置和未命中的地址.这个工具不如其他工具那么精致,但源至少是可用的,所以你总是可以做一些改进.我在另一个答案中详细介绍了这个选项.
perf的主要缺点是使用像cachegrind这样的东西不那么简单.行为和可用事件取决于您的硬件和内核版本,有时堆栈跟踪等操作不起作用等.您必须相对熟悉命令行才能充分利用此工具.
此工具使用相同的基础性能计数器perf,但使用基于GUI的探索,可能更容易跳入perf.它需要更多的自上而下的方法:告诉你问题在哪里并允许你向下钻取,而perf更多的是"这是原始数据,找出错误".
它提供了特定的分析,如内存访问分析,可能适合您的问题.
主要缺点是这是一种付费产品,除非您有资格免费使用它.它可能比使用perf起来更容易,但它仍然不是很容易,而且还有魔法记录,所以如果出现问题,可能很难调试.
1在某些情况下,这可能不是真的.我能想到的主要问题是,如果预取到L2会导致大多数行在丢失之前到达.在这种情况下,L2替换的数量可能可能高于L2未命中的数量.这是一种cachegrind无法帮助你的东西,但perf可以:你可以比较/替换的L2线数和L2未命中数,看看它们是否接近.如果不是,你将不得不与其他计数器一起玩,看看预取是否是原因.