Kcachegrind/callgrind 对于调度程序功能不准确?

2023-12-12

我有一个模型代码,kcachegrind/callgrind 报告了奇怪的结果。这是一种调度程序功能。从 4 个地方呼叫调度员;每个电话都说,实际的do_J运行函数(所以first2只会打电话do_1 and do_2等等)

源代码(这是实际代码的模型)

#define N 1000000

int a[N];
int do_1(int *a) { int i; for(i=0;i<N/4;i++) a[i]+=1; }
int do_2(int *a) { int i; for(i=0;i<N/2;i++) a[i]+=2; }
int do_3(int *a) { int i; for(i=0;i<N*3/4;i++) a[i]+=3; }
int do_4(int *a) { int i; for(i=0;i<N;i++) a[i]+=4; }

int dispatcher(int *a, int j) {
    if(j==1) do_1(a);
    else if(j==2) do_2(a);
    else if(j==3) do_3(a);
    else do_4(a);
}

int first2(int *a) { dispatcher(a,1); dispatcher(a,2); }
int last2(int *a) { dispatcher(a,4); dispatcher(a,3); }
int inner2(int *a) { dispatcher(a,2); dispatcher(a,3); }
int outer2(int *a) { dispatcher(a,1); dispatcher(a,4); }

int main(){
    first2(a);
    last2(a);
    inner2(a);
    outer2(a);
}

编译为gcc -O0;呼叫研磨与valgrind --tool=callgrind; kcache研磨与kcachegrind and qcachegrind-0.7.

这是该应用程序的完整调用图。到 do_J 的所有路径都经过调度程序,这很好(do_1 隐藏得太快了,但它确实在这里,只留给 do_2)

Full

让我们重点关注do_1并检查谁调用了它(这张图片不正确):

enter image description here

我认为这很奇怪first2 and outer2 called do_1但不是所有的。

这是 callgrind/kcachegrind 的限制吗?如何获得带有权重的准确调用图(与每个函数的运行时间成比例,无论有没有子函数)?


是的,这是 callgrind 格式的限制。它不存储完整的跟踪;它只存储父子调用信息。

有一个带有 pprof/libprofiler.so CPU 分析器的 google-perftools 项目,http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html . libprofiler.so可以通过调用跟踪获取配置文件,并且它将存储带有完整回溯的每个跟踪事件。pprof是将 libprofile 的输出转换为图形格式或 callgrind 格式的转换器。在完整视图中,结果将与 kcachegrind 中的结果相同;但如果您专注于某些功能,例如do_1 使用 pprof 的选项焦点;当专注于函数时,它将显示准确的调用树。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kcachegrind/callgrind 对于调度程序功能不准确? 的相关文章

随机推荐