kcachegrind/callgrind가 이상한 결과를보고하는 모델 코드가 있습니다. 일종의 디스패처 기능입니다. 발송자는 4 곳에서 호출됩니다. 각 호출은 실제 do_J
기능을 실행하기 위해 (때문에 first2
만 do_1
및 do_2
등 호출)Kcachegrind/callgrind가 디스패처 기능에 대해 정확하지 않습니까?
#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
로 전화를 걸었다. kcachegrind
및 qcachegrind-0.7
으로 kcachegrinded.
다음은 애플리케이션의 전체적인 콜 그래프입니다. do_J에 대한 모든 경로가 디스패처 통해 이동이 좋다라는 사람,
이 do_1
에 초점을 수 있습니다 및 확인합니다 (do_1가 너무 빨리 고용 했지,하지만 정말 여기에, 그냥 do_2 왼쪽) 그것은 (이 그림은 잘못된 것입니다) :
을 그리고 이것은 단지 first2
및 outer2
전부는 아니지만 do_1
라고, 나는 생각한다, 매우 이상하다.
callgrind/kcachegrind의 제한 사항입니까? 가중치를 가진 정확한 콜 그래프를 얻으려면 어떻게해야합니까? (모든 기능의 실행 시간에 상관없이, 차일드 유무와 상관없이)?
비슷한 문제가 여기에 설명되어 있습니다. [http://www.yosefk.com/blog/how-profilers-lie-the-cases-of-gprof-and-kcachegrind.html] (http : // /www.yosefk.com/blog/how-profilers-lie-the-cases-of-gprof-and-kcachegrind.html) "여기에 우리가 보게 될 것이 있습니다 : ...이 정보는 전화가 무엇인지 알기에 충분하지 않습니다. 나무는 진실을 보여줄 필요가있다. " 그리고 해결 방법이 있습니다 - callstring의 N 슬롯을 기록하기위한 callgrind의'--separate-callers = N' 옵션 – osgx
Valgrind 문서는 callgrind에 대한 유용한 옵션 인'--separate-callers = N' (http : //)을 가지고 있습니다. valgrind.org/docs/manual/cl-manual.html) http://valgrind.org/docs/manual/cl-manual.html#cl-manual.cycles (6.2.4주기 회피) 및 http : // /valgrind.org/docs/manual/cl-manual.html#cl-manual.options.separation (6.3.4 원가 요소 분리 옵션) – osgx