我想描述C ++程序中特定例程的缓存未命中(速率)。我知道一些分析工具,但它们似乎并不能让我满意。
据我所知:
gprof 可以生成调用图和代码覆盖率,但不包括缓存未命中概要。
valgrind (cachegrind)可以分析缓存未命中但似乎只适用于整个应用程序。
oprofile 确实有一个基于符号的输出。但我有点困惑:如果程序A()调用B()(可能是库或系统调用),并且缓存未命中发生在B()内,是否归因于A()?毕竟我想在整个执行A()期间计算缓存未命中。
最后一个问题。 OProfile需要为每个新会话重新启动守护程序。假设我想通过一系列不同的参数和输入来运行我的程序。我怎样才能以自动方式完成?是否有某种方法可以将gettimeofday()插入到代码中以获取缓存统计信息?
答案 0 :(得分:0)
假设特定函数中的缓存未命中是重要的,那么使用cachegrind或oprofile应该可以正常工作。如果你在该函数中的缓存未命中对程序的整个执行并不重要,为什么还要烦恼?
从记忆中,但是我使用oprofile已经过了几年,但你不需要重启守护进程,只需使用"重置我的数据" (opcontrol --reset
)。由于oprofile是系统范围的,您只需使用多个测试用例运行脚本 - oprofile将按流程分割数据,但如果您在任何特定功能中使用高缓存,则应显示在缓存未命中列表中。如果它没有显示,那么缓存中的代码就不会丢失。
我一直在做的方法是编写一个执行opcontrol --reset --start event=CPU_CLK_UNHALTED:400000
的脚本,然后编写我正在测试的程序,然后opcontrol --stop --save=oprofile.result
。
请注意,oprofile是基于统计和样本的,因此您无法测量单个缓存未命中,并且它会记录缓存未命中计数器达到限制的地址。所以,如果你有一个"限制"如果1000个高速缓存未命中,则在函数A中得到999个高速缓存未命中,然后在函数B中出现单个高速缓存未命中,函数B被记入"记入"缓存未命中。但是,假设您没有极其病态的代码,您将在缓存中遗漏的代码区域中获取缓存未命中记录。