Linux에서 실행되는 C++ 응용 프로그램이 있는데 최적화 과정에 있습니다. 내 코드의 어느 부분이 느리게 실행되는지 어떻게 찾아낼 수 있습니까?
질문자 :Gabriel Isenberg
목표가 프로파일러를 사용하는 것이라면 제안된 것 중 하나를 사용하십시오.
그러나 급하고 주관적으로 느린 동안 디버거에서 프로그램을 수동으로 중단할 수 있는 경우 성능 문제를 찾는 간단한 방법이 있습니다.
여러 번 중지하고 매번 호출 스택을 살펴보십시오. 시간의 일정 비율, 20% 또는 50% 또는 무엇이든 낭비하는 코드가 있는 경우 각 샘플의 작업에서 해당 코드를 잡을 확률입니다. 따라서 이는 대략적으로 볼 수 있는 샘플의 백분율입니다. 교육받은 추측이 필요하지 않습니다. 문제가 무엇인지 추측할 수 있다면 이것이 문제를 증명하거나 반증할 것입니다.
크기가 다른 여러 성능 문제가 있을 수 있습니다. 그 중 하나를 제거하면 나머지 부분은 더 많은 비율을 차지하며 후속 패스에서 더 쉽게 발견할 수 있습니다. 이 확대 효과 는 여러 문제에 대해 복합적으로 작용할 때 엄청난 속도 향상 요인으로 이어질 수 있습니다.
주의 사항 : 프로그래머는 직접 사용하지 않는 한 이 기술에 대해 회의적인 경향이 있습니다. 프로파일러가 이 정보를 제공한다고 말하지만 이는 전체 호출 스택을 샘플링한 다음 임의의 샘플 집합을 검사할 수 있는 경우에만 해당됩니다. (요약은 통찰력이 손실되는 곳입니다.) 호출 그래프는 동일한 정보를 제공하지 않습니다.
- 그들은 지시 수준에서 요약하지 않으며,
- 재귀가 있을 때 혼란스러운 요약을 제공합니다.
그들은 또한 그것이 실제로 어떤 프로그램에서나 작동할 때만 그것이 장난감 프로그램에서만 작동한다고 말할 것이고 더 큰 프로그램에서 더 잘 작동하는 것처럼 보일 것입니다. 왜냐하면 그들은 찾아야 할 더 많은 문제가 있는 경향이 있기 때문입니다. 그들은 때때로 문제가 아닌 것을 발견한다고 말하지만 그것은 한 번만 본 경우에만 사실입니다. 하나 이상의 샘플에서 문제가 표시되면 실제입니다.
PS 이것은 Java에서와 같이 특정 시점에서 스레드 풀의 호출 스택 샘플을 수집하는 방법이 있는 경우 다중 스레드 프로그램에서도 수행할 수 있습니다.
PPS 대략적으로 말하자면, 소프트웨어에 추상화 계층이 많을수록 이것이 성능 문제(및 속도 향상의 기회)의 원인이라는 것을 알게 될 가능성이 높아집니다.
추가됨 : 명확하지 않을 수 있지만 스택 샘플링 기술은 재귀가 있는 경우에도 똑같이 잘 작동합니다. 그 이유는 명령을 제거하여 절약할 수 있는 시간은 샘플 내에서 발생할 수 있는 횟수에 관계없이 명령을 포함하는 샘플의 비율로 근사되기 때문입니다.
내가 자주 듣는 또 다른 반대 의견은 " 무작위로 멈추고 실제 문제를 놓칠 것입니다 ."입니다. 이것은 실제 문제가 무엇인지에 대한 사전 개념을 갖는 데서 비롯됩니다. 성능 문제의 주요 속성은 예상을 무시한다는 것입니다. 샘플링을 통해 무언가 문제가 있다는 것을 알 수 있으며 첫 번째 반응은 불신입니다. 그것은 자연스러운 일이지만 문제를 발견하면 그것이 현실이고 그 반대도 마찬가지임을 확신할 수 있습니다.
추가됨 : 작동 방식에 대한 베이지안 설명을 하겠습니다. f
I
(호출 또는 기타)이 있다고 가정합니다(따라서 비용이 많이 듭니다). 단순화를 위해 f
가 무엇인지 모르지만 f가 0.1, 0.2, 0.3, ... 0.9, 1.0이고 이러한 가능성 각각의 사전 확률이 0.1이라고 가정하고 모든 비용은 동일합니다. 아마도 선험적으로.
그런 다음 2개의 스택 샘플만 가져오고 두 샘플에 I
o=2/2
가 표시된다고 가정합니다. 이것은 다음과 같이 I
f
에 대한 새로운 추정치를 제공합니다.
Prior P(f=x) x P(o=2/2|f=x) P(o=2/2&&f=x) P(o=2/2&&f >= x) P(f >= x | o=2/2) 0.1 1 1 0.1 0.1 0.25974026 0.1 0.9 0.81 0.081 0.181 0.47012987 0.1 0.8 0.64 0.064 0.245 0.636363636 0.1 0.7 0.49 0.049 0.294 0.763636364 0.1 0.6 0.36 0.036 0.33 0.857142857 0.1 0.5 0.25 0.025 0.355 0.922077922 0.1 0.4 0.16 0.016 0.371 0.963636364 0.1 0.3 0.09 0.009 0.38 0.987012987 0.1 0.2 0.04 0.004 0.384 0.997402597 0.1 0.1 0.01 0.001 0.385 1 P(o=2/2) 0.385
마지막 열은 예를 들어 f
>= 0.5일 확률이 이전 가정인 60%에서 증가한 92%라고 말합니다.
이전 가정이 다르다고 가정합니다. P(f=0.1)
가 .991(거의 확실함)이고 다른 모든 가능성은 거의 불가능(0.001)이라고 가정합니다. 다시 말해서, 우리의 사전 확신은 I
싸다는 것입니다. 그런 다음 우리는 다음을 얻습니다.
Prior P(f=x) x P(o=2/2|f=x) P(o=2/2&& f=x) P(o=2/2&&f >= x) P(f >= x | o=2/2) 0.001 1 1 0.001 0.001 0.072727273 0.001 0.9 0.81 0.00081 0.00181 0.131636364 0.001 0.8 0.64 0.00064 0.00245 0.178181818 0.001 0.7 0.49 0.00049 0.00294 0.213818182 0.001 0.6 0.36 0.00036 0.0033 0.24 0.001 0.5 0.25 0.00025 0.00355 0.258181818 0.001 0.4 0.16 0.00016 0.00371 0.269818182 0.001 0.3 0.09 0.00009 0.0038 0.276363636 0.001 0.2 0.04 0.00004 0.00384 0.279272727 0.991 0.1 0.01 0.00991 0.01375 1 P(o=2/2) 0.01375
이제 P(f >= 0.5)
는 26%로 이전 가정 0.6%보다 높아졌습니다. I
의 가능한 비용 추정치를 업데이트할 수 있습니다. 데이터 양이 적으면 비용이 얼마인지 정확하게 알려주지 않고 수정할 가치가 있을 만큼만 큽니다.
그것을 보는 또 다른 방법은 계승 법칙 이라고 합니다. 동전을 2번 던지고 앞면이 두 번 나온다면 동전의 가능한 무게에 대해 무엇을 말합니까? 대답하는 존경받는 방법은 평균 값 (number of hits + 1) / (number of tries + 2) = (2+1)/(2+2) = 75%
베타 분포라고 말하는 것입니다.
(핵심은 우리가 I
f
> 0을 제외하고는 많은 것을 말해주지 않습니다.)
따라서 매우 적은 수의 샘플로도 표시되는 명령 비용에 대해 많은 것을 알 수 있습니다. (그리고 평균적으로 비용에 비례하는 빈도로 그것들을 볼 것입니다. n
샘플 f
가 비용인 경우, I
nf+/-sqrt(nf(1-f))
샘플에 나타날 것입니다. 예 , n=10
, f=0.3
, 즉 3+/-1.4
샘플입니다.)
추가됨 : 측정과 무작위 스택 샘플링의 차이점에 대한 직관적인 느낌을 주기 위해:
이제 벽시계 시간에도 스택을 샘플링하는 프로파일러가 있지만 결과 는 측정값(또는 "병목 현상"이 쉽게 숨길 수 있는 핫 경로 또는 핫스팟)입니다. 그들이 당신에게 보여주지 않는(그리고 쉽게 할 수 있는) 것은 실제 샘플 자체입니다. 그리고 목표가 병목 현상을 찾는 것이라면 확인해야 하는 병목 현상의 수는 평균적 으로 2를 소요 시간으로 나눈 값입니다. 따라서 30%의 시간이 소요되면 평균적으로 2/.3 = 6.7개의 샘플이 표시되고 20개의 샘플이 표시될 확률은 99.2%입니다.
다음은 측정 검사와 스택 샘플 검사의 차이점에 대한 실례입니다. 병목 현상은 이와 같은 하나의 큰 덩어리일 수도 있고 수많은 작은 덩어리일 수도 있습니다. 차이가 없습니다.
측정은 수평입니다. 특정 루틴에 소요되는 시간의 비율을 알려줍니다. 샘플링은 수직입니다. 전체 프로그램이 그 순간에 무엇을 하고 있는지 피할 수 있는 방법이 있고 두 번째 샘플 에서 이를 본다면 병목 현상을 발견한 것입니다. 그것이 차이를 만드는 것입니다. 얼마나 많은 시간을 소비했는지뿐만 아니라 시간을 소비하는 전체 이유를 보는 것입니다.
Community Wiki
다음 옵션과 함께 Valgrind 를 사용할 수 있습니다.
valgrind --tool=callgrind ./(Your binary)
callgrind.out.x
라는 파일을 생성합니다. 그런 다음 kcachegrind
도구를 사용하여 이 파일을 읽을 수 있습니다. 어떤 라인의 비용이 얼마인지와 같은 결과와 함께 사물에 대한 그래픽 분석을 제공합니다.
Ajay
나는 당신이 GCC를 사용하고 있다고 가정합니다. 표준 솔루션은 gprof 로 프로파일링하는 것입니다.
프로파일링하기 전에 컴파일 -pg
를 추가해야 합니다.
cc -o myprog myprog.c utils.c -g -pg
아직 시도하지 않았지만 google-perftools 에 대해 좋은 소식을 들었습니다. 시도해 볼 가치가 있습니다.
관련 질문 여기 .
gprof
가 당신을 위해 일하지 않는다면 몇 가지 다른 유행어 : Valgrind , Intel VTune , Sun DTrace .
Nazgob
최신 커널(예: 최신 Ubuntu 커널)은 새로운 'perf' 도구( apt-get install linux-tools
)(일명 perf_events )와 함께 제공됩니다.
여기에는 고전적인 샘플링 프로파일러( man-page )와 멋진 타임차트가 함께 제공됩니다!
중요한 것은 이러한 도구가 단순히 프로세스 프로파일링이 아니라 시스템 프로파일링 이 될 수 있다는 것입니다. 이 도구는 스레드, 프로세스 및 커널 간의 상호 작용을 보여주고 프로세스 간의 스케줄링 및 I/O 종속성을 이해할 수 있도록 합니다.
Will
valgrind --tool=callgrind
실행에 대한 답변은 몇 가지 옵션 없이는 완전하지 않습니다. 우리는 일반적으로 Valgrind에서 10분의 느린 시작 시간을 프로파일링하고 싶지 않고 어떤 작업을 수행할 때 프로그램을 프로파일링하기를 원합니다.
그래서 이것이 제가 추천하는 것입니다. 먼저 프로그램을 실행하십시오.
valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp
이제 작동하고 프로파일링을 시작하려면 다른 창에서 실행해야 합니다.
callgrind_control -i on
그러면 프로파일링이 켜집니다. 그것을 끄고 전체 작업을 중지하려면 다음을 사용할 수 있습니다.
callgrind_control -k
이제 현재 디렉토리에 callgrind.out.*라는 파일이 있습니다. 프로파일링 결과를 보려면 다음을 사용하십시오.
kcachegrind callgrind.out.*
다음 창에서 "Self" 열 헤더를 클릭하는 것이 좋습니다. 그렇지 않으면 "main()"이 가장 시간이 많이 걸리는 작업으로 표시됩니다. "Self"는 종속 항목이 아닌 각 기능 자체에 시간이 얼마나 걸렸는지 보여줍니다.
Tõnu Samuel
Valgrind와 Callgrind를 프로파일링 도구 모음의 기반으로 사용합니다. 알아야 할 중요한 것은 Valgrind가 기본적으로 가상 머신이라는 것입니다.
(wikipedia) Valgrind는 본질적으로 동적 재컴파일을 포함하여 JIT(Just-In-Time) 컴파일 기술을 사용하는 가상 머신입니다. 원래 프로그램의 어떤 것도 호스트 프로세서에서 직접 실행되지 않습니다. 대신 Valgrind는 먼저 프로그램을 프로세서 중립적인 SSA 기반 형식인 Intermediate Representation(IR)이라고 하는 임시적이고 단순한 형식으로 변환합니다. 변환 후 도구(아래 참조)는 Valgrind가 IR을 기계 코드로 다시 변환하고 호스트 프로세서가 실행하도록 하기 전에 IR에서 원하는 대로 변환할 수 있습니다.
Callgrind는 이를 기반으로 하는 프로파일러입니다. 주요 이점은 신뢰할 수 있는 결과를 얻기 위해 몇 시간 동안 애플리케이션을 실행할 필요가 없다는 것입니다. Callgrind는 비프로빙 프로파일러이기 때문에 1초만 실행해도 견고하고 신뢰할 수 있는 결과를 얻을 수 있습니다.
Valgrind를 기반으로 하는 또 다른 도구는 Massif입니다. 힙 메모리 사용량을 프로파일링하는 데 사용합니다. 그것은 잘 작동합니다. 그것이 하는 일은 메모리 사용에 대한 스냅샷을 제공한다는 것입니다. 자세한 정보 WHAT가 메모리의 몇 퍼센트를 보유하고 있으며 누가 그것을 저장했는지에 대한 정보입니다. 이러한 정보는 애플리케이션 실행의 다른 시점에서 사용할 수 있습니다.
anon
이것은 Nazgob의 Gprof 답변에 대한 답변 입니다.
저는 지난 며칠간 Gprof를 사용해 왔으며 이미 세 가지 중요한 제한 사항을 발견했습니다. 그 중 하나는 다른 곳에서는 아직 문서화되지 않은 것입니다.
해결 방법 을 사용하지 않는 한 다중 스레드 코드에서 제대로 작동하지 않습니다.
호출 그래프는 함수 포인터로 인해 혼란스러워집니다. 예: 지정된 배열(둘 다 인수로 전달됨)에 대해 지정된 함수를 다중 스레드할 수 있는
multithread()
multithread()
대한 모든 호출을 자식에 소요되는 시간을 계산하는 목적과 동일하게 봅니다.multithread()
전달하는 일부 함수는 다른 함수보다 훨씬 오래 걸리기 때문에 내 호출 그래프는 대부분 쓸모가 없습니다. (여기서 스레딩이 문제인지 궁금해하는 사람들에게: 아니요,multithread()
는 선택적으로 가능하고 이 경우에는 호출 스레드에서만 모든 것을 순차적으로 실행할 수 있습니다).여기 에서 "...호출 건수 수치는 샘플링이 아닌 계산으로 파생됩니다. 완전히 정확합니다..."라고 말합니다. 그러나 가장 많이 호출되는 함수에 대한 호출 통계로 5345859132+784984078을 제공하는 호출 그래프를 찾았습니다. 여기서 첫 번째 번호는 직접 호출이고 두 번째 재귀 호출은 모두 자체 호출입니다. 이것은 내가 버그를 가지고 있다는 것을 의미하기 때문에 코드에 긴(64비트) 카운터를 넣고 동일한 실행을 다시 수행했습니다. 내 수: 5345859132 직접 및 78094395406 자가 재귀 호출. 거기에는 많은 숫자가 있으므로 내가 측정한 재귀 호출은 780억이고 Gprof의 7억 8400만입니다. 100배 다른 요소입니다. 두 실행 모두 단일 스레드 및 최적화되지 않은 코드였습니다.
-g
이고 다른 하나는-pg
누군가에게 도움이 된다면 64비트 Debian Lenny에서 실행되는 GNU Gprof(GNU Binutils for Debian) 2.18.0.20080103이었습니다.
Rob_before_edits
C++ 프로파일링 기술 조사: gprof vs valgrind vs perf vs gperftools
이 답변에서는 도구가 작동하는 방식을 구체적으로 비교하기 위해 몇 가지 매우 간단한 테스트 프로그램을 분석하기 위해 여러 도구를 사용할 것입니다.
다음 테스트 프로그램은 매우 간단하며 다음을 수행합니다.
main
호출은fast
및maybe_slow
3회,maybe_slow
호출 중 하나는 느림maybe_slow
의 느린 호출은 10배 더 길고 자식 함수에 대한 호출을common
고려하면 런타임을 지배합니다. 이상적으로는 프로파일링 도구가 특정 느린 호출을 가리킬 수 있습니다.fast
및maybe_slow
모두 프로그램 실행의 대부분을 차지하는common
호출프로그램 인터페이스는 다음과 같습니다.
./main.out [n [seed]]
프로그램은 총
O(n^2)
루프를 수행합니다.seed
는 런타임에 영향을 미치지 않고 다른 출력을 얻는 것입니다.
메인.c
#include <inttypes.h> #include <stdio.h> #include <stdlib.h> uint64_t __attribute__ ((noinline)) common(uint64_t n, uint64_t seed) { for (uint64_t i = 0; i < n; ++i) { seed = (seed * seed) - (3 * seed) + 1; } return seed; } uint64_t __attribute__ ((noinline)) fast(uint64_t n, uint64_t seed) { uint64_t max = (n / 10) + 1; for (uint64_t i = 0; i < max; ++i) { seed = common(n, (seed * seed) - (3 * seed) + 1); } return seed; } uint64_t __attribute__ ((noinline)) maybe_slow(uint64_t n, uint64_t seed, int is_slow) { uint64_t max = n; if (is_slow) { max *= 10; } for (uint64_t i = 0; i < max; ++i) { seed = common(n, (seed * seed) - (3 * seed) + 1); } return seed; } int main(int argc, char **argv) { uint64_t n, seed; if (argc > 1) { n = strtoll(argv[1], NULL, 0); } else { n = 1; } if (argc > 2) { seed = strtoll(argv[2], NULL, 0); } else { seed = 0; } seed += maybe_slow(n, seed, 0); seed += fast(n, seed); seed += maybe_slow(n, seed, 1); seed += fast(n, seed); seed += maybe_slow(n, seed, 0); seed += fast(n, seed); printf("%" PRIX64 "\n", seed); return EXIT_SUCCESS; }
gprof
gprof는 계측을 사용하여 소프트웨어를 다시 컴파일해야 하며 해당 계측과 함께 샘플링 접근 방식도 사용합니다. 따라서 정확도(샘플링이 항상 완전히 정확하지는 않으며 기능을 건너뛸 수 있음)와 실행 속도 저하(계측 및 샘플링은 실행 속도를 크게 저하시키지 않는 비교적 빠른 기술임) 사이의 균형을 유지합니다.
gprof는 GCC/binutils에 내장되어 있으므로 -pg
옵션을 사용하여 컴파일하기만 하면 됩니다. 10000
)의 합리적인 실행 시간을 생성하는 size CLI 매개변수를 사용하여 프로그램을 정상적으로 실행합니다.
gcc -pg -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c time ./main.out 10000
교육상의 이유로 최적화가 활성화되지 않은 상태에서도 실행됩니다. 이것은 일반적으로 최적화된 프로그램의 성능 최적화에만 관심을 갖기 때문에 실제로는 쓸모가 없습니다.
gcc -pg -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c ./main.out 10000
첫째, time
-pg
사용하거나 사용하지 않은 실행 시간이 동일하다는 것을 알려줍니다. 그러나 예를 들어 이 티켓에 표시된 것처럼 복잡한 소프트웨어에서 2배 - 3배의 속도 저하에 대한 설명을 보았습니다.
-pg
컴파일했기 때문에 프로그램을 실행하면 프로파일링 데이터가 포함된 gmon.out
다음에서 질문한 대로 gprof2dot
를 사용하여 해당 파일을 그래픽으로 관찰할 수 있습니다 . gprof 결과의 그래픽 표현을 얻을 수 있습니까?
sudo apt install graphviz python3 -m pip install --user gprof2dot gprof main.out > main.gprof gprof2dot < main.gprof | dot -Tsvg -o output.svg
여기에서 gprof
도구는 gmon.out
gprof2dot
에서 사람이 읽을 수 있는 보고서 main.gprof
는 이 보고서를 읽고 그래프를 생성합니다.
gprof2dot의 소스는 https://github.com/jrfonseca/gprof2dot입니다.
-O0
실행에 대해 다음을 관찰합니다.
-O3
실행의 경우:
-O0
출력은 거의 자명합니다. 예를 들어, 3개의 maybe_slow
호출과 해당 하위 호출이 전체 실행 시간의 97.56%를 차지 maybe_slow
가 없는 may_slow 자체의 실행은 전체 실행 시간의 0.00%를 차지합니다. 아동 전화에 소비했습니다.
TODO: bt
에서 볼 수 있음에도 불구 -O3
main
누락된 이유는 무엇입니까? GProf 출력에서 누락된 기능은 gprof가 컴파일된 계측 외에도 샘플링을 기반으로 하고 있고 -O3
main
이 너무 빠르고 샘플이 없기 때문이라고 생각합니다.
SVG는 Ctrl + F로 검색할 수 있고 파일 크기는 약 10배 더 작을 수 있기 때문에 PNG 대신 SVG 출력을 선택합니다. 또한 생성된 이미지의 너비와 높이는 복잡한 소프트웨어의 경우 수만 픽셀로 엄청날 수 있으며 eog
3.28.1 버그가 발생하는 반면 SVG는 내 브라우저에서 자동으로 열립니다. 김프 2.8은 잘 작동했지만 다음을 참조하십시오.
- https://askubuntu.com/questions/1112641/how-to-view-extremely-large-images
- https://unix.stackexchange.com/questions/77968/viewing-large-image-on-linux
- https://superuser.com/questions/356038/viewer-for-huge-images-under-linux-100-mp-color-images
그러나 그때에도 원하는 것을 찾기 위해 이미지를 많이 드래그하게 될 것입니다. 예를 들어 이 티켓 에서 가져온 "실제" 소프트웨어 예제의 이 이미지를 참조하십시오.
정렬되지 않은 작은 스파게티 라인이 서로 교차하는 가장 중요한 호출 스택을 쉽게 찾을 수 있습니까? 더 나은 dot
옵션이 분명히 있을 수 있지만 지금은 거기에 가고 싶지 않습니다. 우리에게 정말 필요한 것은 적절한 전용 뷰어이지만 아직 찾지 못했습니다.
그러나 컬러 맵을 사용하여 이러한 문제를 약간 완화할 수 있습니다. 예를 들어, 이전의 거대한 이미지에서 나는 마침내 왼쪽에서 중요한 경로를 찾았습니다. 나는 녹색이 빨간색 다음에 오고 마지막으로 더 어둡고 더 어두운 파란색이 온다는 화려한 추론을 만들었습니다.
또는 이전에 저장 gprof
내장 binutils 도구의 텍스트 출력을 관찰할 수도 있습니다.
cat main.gprof
기본적으로 이것은 출력 데이터의 의미를 설명하는 매우 자세한 출력을 생성합니다. 이보다 더 잘 설명할 수 없기 때문에 직접 읽어보시도록 하겠습니다.
-b
옵션을 사용하여 자습서 없이 데이터만 표시하도록 자세한 정보를 줄일 수 있습니다.
gprof -b main.out
이 예에서 출력은 -O0
에 대한 것이었습니다.
Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls s/call s/call name 100.35 3.67 3.67 123003 0.00 0.00 common 0.00 3.67 0.00 3 0.00 0.03 fast 0.00 3.67 0.00 3 0.00 1.19 maybe_slow Call graph granularity: each sample hit covers 2 byte(s) for 0.27% of 3.67 seconds index % time self children called name 0.09 0.00 3003/123003 fast [4] 3.58 0.00 120000/123003 maybe_slow [3] [1] 100.0 3.67 0.00 123003 common [1] ----------------------------------------------- <spontaneous> [2] 100.0 0.00 3.67 main [2] 0.00 3.58 3/3 maybe_slow [3] 0.00 0.09 3/3 fast [4] ----------------------------------------------- 0.00 3.58 3/3 main [2] [3] 97.6 0.00 3.58 3 maybe_slow [3] 3.58 0.00 120000/123003 common [1] ----------------------------------------------- 0.00 0.09 3/3 main [2] [4] 2.4 0.00 0.09 3 fast [4] 0.09 0.00 3003/123003 common [1] ----------------------------------------------- Index by function name [1] common [4] fast [3] maybe_slow
-O3
:
Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls us/call us/call name 100.52 1.84 1.84 123003 14.96 14.96 common Call graph granularity: each sample hit covers 2 byte(s) for 0.54% of 1.84 seconds index % time self children called name 0.04 0.00 3003/123003 fast [3] 1.79 0.00 120000/123003 maybe_slow [2] [1] 100.0 1.84 0.00 123003 common [1] ----------------------------------------------- <spontaneous> [2] 97.6 0.00 1.79 maybe_slow [2] 1.79 0.00 120000/123003 common [1] ----------------------------------------------- <spontaneous> [3] 2.4 0.00 0.04 fast [3] 0.04 0.00 3003/123003 common [1] ----------------------------------------------- Index by function name [1] common
각 섹션에 대한 매우 빠른 요약 예:
0.00 3.58 3/3 main [2] [3] 97.6 0.00 3.58 3 maybe_slow [3] 3.58 0.00 120000/123003 common [1]
들여쓰기된 함수를 중심으로 합니다( maybe_flow
). [3]
은 해당 함수의 ID입니다. 함수 위에는 호출자가 있고 그 아래에는 호출자가 있습니다.
-O3
maybe_slow
및 fast
에 알려진 부모가 없는 그래픽 출력과 같이 여기를 참조하십시오 <spontaneous>
의미한다고 말하는 것입니다.
gprof를 사용하여 라인별 프로파일링을 수행하는 좋은 방법이 있는지 잘 모르겠습니다: `gprof` 특정 코드 라인에서 보낸 시간
valgrind 콜그라인드
valgrind는 valgrind 가상 머신을 통해 프로그램을 실행합니다. 이렇게 하면 프로파일링이 매우 정확해 지지만 프로그램 속도가 매우 느려집니다. 또한 이전에 kcachegrind에 대해 언급한 적이 있습니다. 코드의 그림 함수 호출 그래프를 가져오는 도구
callgrind는 코드를 프로파일링하는 valgrind의 도구이고 kcachegrind는 cachegrind 출력을 시각화할 수 있는 KDE 프로그램입니다.
-pg
플래그를 제거해야 합니다 Profiling timer expired
되어 실행이 실제로 실패합니다. 예, 이것은 너무 일반적이어서 제가 그랬고 이에 대한 스택 오버플로 질문이 있었습니다.
따라서 다음과 같이 컴파일하고 실행합니다.
sudo apt install kcachegrind valgrind gcc -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c time valgrind --tool=callgrind valgrind --dump-instr=yes \ --collect-jumps=yes ./main.out 10000
--dump-instr=yes --collect-jumps=yes
를 활성화하면 비교적 적은 추가 오버헤드 비용으로 어셈블리 라인별 성능 분석을 볼 수 있는 정보도 덤프하기 때문입니다.
기본적으로 time
은 프로그램을 실행하는 데 29.5초가 걸렸다고 알려 주므로 이 예제에서는 속도가 약 15배 느려졌습니다. 분명히 이 속도 저하가 더 큰 워크로드에 심각한 제한이 될 것입니다. 여기에 언급된 "실제 소프트웨어 예제"에서 80배의 속도 저하를 관찰했습니다.
callgrind.out.<pid>
라는 프로필 데이터 파일이 생성됩니다(예: 내 경우에는 callgrind.out.8554
우리는 그 파일을 다음과 같이 봅니다:
kcachegrind callgrind.out.8554
텍스트 gprof 출력과 유사한 데이터가 포함된 GUI를 보여줍니다.
또한, 우측 하단의 "Call Graph" 탭으로 이동하면, 우클릭으로 내보낼 수 있는 콜 그래프를 볼 수 있으며, 흰색 테두리가 터무니없이 많은 다음 이미지를 얻을 수 있습니다 :-)
kcachegrind는 호출 시간이 너무 짧기 때문에 시각화를 단순화해야 하기 때문에 해당 그래프에 fast
가 표시되지 않는다고 생각합니다. 이는 실제 프로그램에서 원하는 동작일 수 있습니다. 오른쪽 클릭 메뉴에는 이러한 노드를 컬링할 시기를 제어하는 몇 가지 설정이 있지만 빠른 시도 후에는 짧은 호출을 표시하지 못했습니다. 내가 클릭하면 fast
왼쪽 창에서, 그것과 콜 그래프 표시됩니까 fast
그 스택이 실제로 캡처 그래서. 아무도 아직 완전한 그래프 콜 그래프를 표시 할 수있는 방법을 발견했다 : 만들기가 kcachegrind 콜 그래프의 모든 함수 호출을 보여 callgrind
TODO 복잡한 C ++ 소프트웨어, I 형의 일부 항목 참조 <cycle N>
, 예를 들어 <cycle 11>
나는 함수 이름을 기대하는 경우, 그 의미를 무엇? 켜고 끌 수 있는 "주기 감지" 버튼이 있다는 것을 알았습니다. 하지만 그것은 무엇을 의미합니까?
linux-tools
perf
perf
는 독점적으로 Linux 커널 샘플링 메커니즘을 사용하는 것 같습니다. 이렇게 하면 설정이 매우 간단하지만 완전히 정확하지는 않습니다.
sudo apt install linux-tools time perf record -g ./main.out 10000
이것은 실행에 0.2초를 추가했기 때문에 시간적으로는 문제가 없지만 키보드 오른쪽 화살표로 common
Samples: 7K of event 'cycles:uppp', Event count (approx.): 6228527608 Children Self Command Shared Object Symbol - 99.98% 99.88% main.out main.out [.] common common 0.11% 0.11% main.out [kernel] [k] 0xffffffff8a6009e7 0.01% 0.01% main.out [kernel] [k] 0xffffffff8a600158 0.01% 0.00% main.out [unknown] [k] 0x0000000000000040 0.01% 0.00% main.out ld-2.27.so [.] _dl_sysdep_start 0.01% 0.00% main.out ld-2.27.so [.] dl_main 0.01% 0.00% main.out ld-2.27.so [.] mprotect 0.01% 0.00% main.out ld-2.27.so [.] _dl_map_object 0.01% 0.00% main.out ld-2.27.so [.] _xstat 0.00% 0.00% main.out ld-2.27.so [.] __GI___tunables_init 0.00% 0.00% main.out [unknown] [.] 0x2f3d4f4944555453 0.00% 0.00% main.out [unknown] [.] 0x00007fff3cfc57ac 0.00% 0.00% main.out ld-2.27.so [.] _start
그런 다음 -O0 프로그램을 벤치마킹하여 -O0
하려고 합니다. 그리고 마침내 이제서야 호출 그래프가 표시됩니다.
Samples: 15K of event 'cycles:uppp', Event count (approx.): 12438962281 Children Self Command Shared Object Symbol + 99.99% 0.00% main.out [unknown] [.] 0x04be258d4c544155 + 99.99% 0.00% main.out libc-2.27.so [.] __libc_start_main - 99.99% 0.00% main.out main.out [.] main - main - 97.54% maybe_slow common - 2.45% fast common + 99.96% 99.85% main.out main.out [.] common + 97.54% 0.03% main.out main.out [.] maybe_slow + 2.45% 0.00% main.out main.out [.] fast 0.11% 0.11% main.out [kernel] [k] 0xffffffff8a6009e7 0.00% 0.00% main.out [unknown] [k] 0x0000000000000040 0.00% 0.00% main.out ld-2.27.so [.] _dl_sysdep_start 0.00% 0.00% main.out ld-2.27.so [.] dl_main 0.00% 0.00% main.out ld-2.27.so [.] _dl_lookup_symbol_x 0.00% 0.00% main.out [kernel] [k] 0xffffffff8a600158 0.00% 0.00% main.out ld-2.27.so [.] mmap64 0.00% 0.00% main.out ld-2.27.so [.] _dl_map_object 0.00% 0.00% main.out ld-2.27.so [.] __GI___tunables_init 0.00% 0.00% main.out [unknown] [.] 0x552e53555f6e653d 0.00% 0.00% main.out [unknown] [.] 0x00007ffe1cf20fdb 0.00% 0.00% main.out ld-2.27.so [.] _start
-O3
실행에서 무슨 일이 일어났습니까? 단순히 maybe_slow
및 fast
가 너무 빨라 샘플을 얻지 못했습니까? 실행하는 데 더 오래 걸리는 더 큰 프로그램 -O3
와 잘 작동합니까? 일부 CLI 옵션을 놓쳤습니까? Hertz에서 샘플 주파수를 제어하기 위해 -F
에 대해 알아 -F 39500
sudo
로 늘릴 수 있음)까지 올렸지만 여전히 명확한 호출이 보이지 않습니다.
perf
멋진 점 중 하나는 Brendan Gregg의 FlameGraph 도구입니다. 이 도구는 큰 호출을 빠르게 볼 수 있는 매우 깔끔한 방식으로 호출 스택 타이밍을 표시합니다. 이 도구는 https://github.com/brendangregg/FlameGraph 에서 사용할 수 있으며 그의 perf 자습서(http://www.brendangregg.com/perf.html#FlameGraphs )에도 언급되어 있습니다. sudo
없이 perf
를 실행했을 때 ERROR: No stack counts found
없으므로 지금은 sudo
로 수행하겠습니다.
git clone https://github.com/brendangregg/FlameGraph sudo perf record -F 99 -g -o perf_with_stack.data ./main.out 10000 sudo perf script -i perf_with_stack.data | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
그러나 이러한 간단한 프로그램에서 출력은 이해하기 쉽지 않습니다. 그 그래프에서 maybe_slow
또는 fast
더 복잡한 예에서는 그래프가 의미하는 바가 명확해집니다.
[unknown]
기능의 로그가 있습니다. 그 이유는 무엇입니까?
그만한 가치가 있는 또 다른 성능 GUI 인터페이스는 다음과 같습니다.
Eclipse 추적 나침반 플러그인: https://www.eclipse.org/tracecompass/
그러나이 먼저 변환에 함께 할 수있는 공통 추적 형식에 데이터를 가지고 있다는 단점이있다
perf data --to-ctf
하지만 빌드시에 활성화 될 필요가 /이perf
, 새로운 충분히 둘 중 하나의 Ubuntu 18.04의 성능은 그렇지 않습니다.https://github.com/KDAB/hotspot
이것의 단점은 Ubuntu 패키지가 없는 것 같고, 빌드하려면 Qt 5.10이 필요하고 Ubuntu 18.04는 Qt 5.9에 있다는 것입니다.
gperftools
이전에는 "Google 성능 도구"라고 불렀고 출처: https://github.com/gperftools/gperftools 샘플 기반.
먼저 다음을 사용하여 gperftools를 설치합니다.
sudo apt install google-perftools
그런 다음 런타임 시 또는 빌드 시의 두 가지 방법으로 gperftools CPU 프로파일러를 활성화할 수 있습니다.
런타임에, 우리는 libprofiler.so
를 가리키 LD_PRELOAD
를 전달해야 합니다. libprofiler.so 는 내 시스템에서 locate libprofiler.so
수 있습니다.
gcc -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so \ CPUPROFILE=prof.out ./main.out 10000
또는 링크 타임에 라이브러리를 빌드하여 런타임에 LD_PRELOAD
gcc -Wl,--no-as-needed,-lprofiler,--as-needed -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c CPUPROFILE=prof.out ./main.out 10000
참조: gperftools - 프로필 파일이 덤프되지 않음
지금까지 내가 찾은 이 데이터를 보는 가장 좋은 방법은 kcachegrind가 입력으로 사용하는 것과 동일한 형식(예, Valgrind-project-viewer-tool)을 pprof 출력으로 만들고 kcachegrind를 사용하여 다음을 확인하는 것입니다.
google-pprof --callgrind main.out prof.out > callgrind.out kcachegrind callgrind.out
이러한 방법 중 하나로 실행한 후 prof.out
프로필 데이터 파일을 출력으로 얻습니다. 다음을 사용하여 해당 파일을 SVG로 그래픽으로 볼 수 있습니다.
google-pprof --web main.out prof.out
이것은 다른 도구와 마찬가지로 친숙한 호출 그래프로 제공하지만 초가 아닌 샘플 수의 투박한 단위를 사용합니다.
또는 다음을 사용하여 일부 텍스트 데이터를 얻을 수도 있습니다.
google-pprof --text main.out prof.out
다음을 제공합니다.
Using local file main.out. Using local file prof.out. Total: 187 samples 187 100.0% 100.0% 187 100.0% common 0 0.0% 100.0% 187 100.0% __libc_start_main 0 0.0% 100.0% 187 100.0% _start 0 0.0% 100.0% 4 2.1% fast 0 0.0% 100.0% 187 100.0% main 0 0.0% 100.0% 183 97.9% maybe_slow
원시 perf_event_open 시스템 perf_event_open
코드 계측
perf
사용하는 것과 동일한 기본 하위 시스템이라고 생각하지만 물론 관심 이벤트로 컴파일 타임에 프로그램을 명시적으로 계측함으로써 훨씬 더 큰 제어를 얻을 수 있습니다.
이것은 대부분의 사람들에게 너무 하드코어할 수 있지만 일종의 재미입니다. 실행 가능한 최소 예제: C 프로그램에서 실행된 명령어 수를 빠르게 계산하는 방법
인텔 VTune
https://en.wikipedia.org/wiki/VTune
이것은 비공개 소스이고 x86 전용인 것 같지만 내가 들은 바에 따르면 놀라운 것 같습니다. 얼마나 무료인지는 모르겠지만 다운로드는 무료인 것 같습니다. TODO 평가.
Ubuntu 18.04, gprof2dot 2019.11.30, valgrind 3.13.0, perf 4.15.18, Linux 커널 4.15.0, FLameGraph 1a0dc6985aad06e76857cf2a359bd5b0c.
Ciro Santilli 新疆再教育营六四事件法轮功郝海东
Valgrind, callgrind 및 kcachegrind 사용:
valgrind --tool=callgrind ./(Your binary)
callgrind.out.x를 생성합니다. kcachegrind를 사용하여 읽으십시오.
gprof 사용(-pg 추가):
cc -o myprog myprog.c utils.c -g -pg
(다중 스레드, 함수 포인터에는 좋지 않음)
google-perftools 사용:
시간 샘플링을 사용하여 I/O 및 CPU 병목 현상이 드러납니다.
Intel VTune이 최고입니다(교육용 무료).
기타: AMD Codeanalyst(AMD CodeXL로 대체됨), OProfile, 'perf' 도구(apt-get install linux-tools)
Ehsan
단일 스레드 프로그램의 경우 igprof , The Ignominous Profiler: https://igprof.org/ 를 사용할 수 있습니다.
Mike Dunlavey의 ... long... 답변 라인을 따라가는 샘플링 프로파일러입니다. 이는 결과를 탐색 가능한 호출 스택 트리에 선물 포장하고 각 함수에 소요된 시간이나 메모리가 누적되거나 기능별.
fwyzard
또한 언급할 가치가 있는 것은
- HPCToolkit( http://hpctoolkit.org/ ) - 오픈 소스로 병렬 프로그램에서 작동하며 여러 방법으로 결과를 볼 수 있는 GUI가 있습니다.
- Intel VTune( https://software.intel.com/en-us/vtune ) - Intel 컴파일러가 있는 경우 매우 좋습니다.
- TAU ( http://www.cs.uoregon.edu/research/tau/home.php )
HPCToolkit 및 VTune을 사용했으며 텐트에서 긴 극을 찾는 데 매우 효과적이며 코드를 다시 컴파일할 필요가 없습니다(단, 의미 있는 출력을 얻으려면 CMake에서 -g -O 또는 RelWithDebInfo 유형 빌드를 사용해야 함) . 나는 TAU가 능력면에서 비슷하다고 들었습니다.
raovgarimella
다음은 코드 속도를 높이는 데 사용하는 두 가지 방법입니다.
CPU 바운드 애플리케이션의 경우:
- 디버그 모드에서 프로파일러를 사용하여 코드에서 의심스러운 부분 식별
- 그런 다음 RELEASE 모드로 전환하고 성능에 변화가 나타날 때까지 코드에서 의심스러운 부분을 주석 처리합니다(아무것도 넣지 않음).
I/O 바운드 애플리케이션의 경우:
- RELEASE 모드에서 프로파일러를 사용하여 코드에서 의심스러운 부분을 식별합니다.
주의
프로파일러가 없으면 가난한 사람의 프로파일러를 사용하십시오. 애플리케이션을 디버깅하는 동안 일시 중지를 누르십시오. 대부분의 개발자 제품군은 주석 처리된 줄 번호가 있는 어셈블리로 나뉩니다. 통계적으로 CPU 주기의 대부분을 차지하는 지역에 도착할 가능성이 높습니다.
CPU의 경우 디버그 모드에서 프로파일링하는 이유 는 RELEASE 모드에서 프로파일링을 시도하면 컴파일러가 수학, 벡터화 루프 및 코드를 조립할 때 매핑할 수 없는 엉망으로 만드는 경향이 있는 인라인 함수를 줄이기 때문입니다. 매핑할 수 없는 엉망은 어셈블리가 최적화 중인 소스 코드와 일치하지 않을 수 있기 때문에 프로파일러가 시간이 오래 걸리는 것을 명확하게 식별할 수 없음을 의미합니다 . RELEASE 모드의 성능(예: 타이밍에 민감한)이 필요한 경우 사용 가능한 성능을 유지하기 위해 필요에 따라 디버거 기능을 비활성화하십시오.
I/O 바운드의 경우 I/O 작업이 공유 라이브러리(대부분의 경우)에 외부적으로 연결되거나 최악의 경우 시스템 오류가 발생하기 때문에 프로파일러는 RELEASE 모드에서 I/O 작업을 식별할 수 있습니다. 호출 인터럽트 벡터(프로파일러에서도 쉽게 식별할 수 있음).
seo
프로파일링에 유용하게 사용할 수 있는 타임스탬프와 총 가동 시간이 포함되어 있으므로 loguru
와 같은 로깅 프레임워크를 사용할 수 있습니다.
BullyWiiPlaza
실제로 google/benchmark 에 대해 언급된 사람이 많지 않은 것에 약간 놀랐습니다. 특히 코드 기반이 약간 큰 경우 특정 코드 영역을 고정하는 것이 약간 callgrind
병목 현상을 일으키는 부분을 식별하는 IMHO가 여기서 핵심입니다. 그러나 먼저 다음 질문에 답하고 이에 따라 도구를 선택하겠습니다.
- 내 알고리즘이 맞습니까?
- 병목 현상이 나타나는 잠금 장치가 있습니까?
- 범인으로 판명된 코드의 특정 섹션이 있습니까?
- 처리 및 최적화된 IO는 어떻습니까?
valgrind
의 조합으로 callgrind
및 kcachegrind
위의 점에서 괜찮은 평가를 제공해야하며,이 코드의 일부 섹션에 문제가 있다는 것을 설립 된 후에는, 내가 마이크로 벤치 마크를 수행하는 게 좋을 것 - google benchmark
에 좋은 장소입니다 시작.
Potato
iprof 라이브러리를 사용할 수 있습니다.
https://gitlab.com/Neurochrom/iprof
https://github.com/Neurochrom/iprof
크로스 플랫폼이며 실시간으로 애플리케이션의 성능을 측정하지 않아도 됩니다. 라이브 그래프와 결합할 수도 있습니다. 전체 면책 조항: 저는 저자입니다.
N3UR0CHR0M
직장에서 우리는 스케줄링 측면에서 우리가 원하는 것을 모니터링하는 데 도움이 되는 정말 좋은 도구를 가지고 있습니다. 이것은 여러 번 유용했습니다.
C++로 되어 있으며 필요에 따라 사용자 정의해야 합니다. 불행히도 코드는 공유할 수 없고 개념만 공유할 수 있습니다. 타임스탬프와 이벤트 ID가 포함된 "대형" volatile
버퍼를 사용하여 사후에 덤프할 수 있거나 로깅 시스템을 중지한 후(예를 들어 이를 파일로 덤프할 수 있습니다).
모든 데이터가 포함된 소위 대형 버퍼를 검색하고 작은 인터페이스가 이를 구문 분석하고 오실로스코프가 색상( .hpp
파일에 구성)으로 수행하는 것처럼 이름(위/아래 + 값)으로 이벤트를 표시합니다.
생성된 이벤트의 양을 사용자 정의하여 원하는 것에만 집중할 수 있습니다. 초당 기록된 이벤트의 양을 기반으로 원하는 CPU 양을 소비하면서 문제를 예약하는 데 많은 도움이 되었습니다.
3개의 파일이 필요합니다.
toolname.hpp // interface toolname.cpp // code tool_events_id.hpp // Events ID
tool_events_id.hpp
에서 이벤트를 정의하는 것입니다.
// EVENT_NAME ID BEGIN_END BG_COLOR NAME #define SOCK_PDU_RECV_D 0x0301 //@D00301 BGEEAAAA # TX_PDU_Recv #define SOCK_PDU_RECV_F 0x0302 //@F00301 BGEEAAAA # TX_PDU_Recv
toolname.hpp
에서 몇 가지 함수를 정의합니다.
#define LOG_LEVEL_ERROR 0 #define LOG_LEVEL_WARN 1 // ... void init(void); void probe(id,payload); // etc
코드 어디에서나 다음을 사용할 수 있습니다.
toolname<LOG_LEVEL>::log(EVENT_NAME,VALUE);
probe
기능은 몇 개의 어셈블리 라인을 사용하여 최대한 빨리 시계 타임스탬프를 검색한 다음 버퍼에 항목을 설정합니다. 또한 로그 이벤트를 저장할 인덱스를 안전하게 찾기 위한 원자적 증분이 있습니다. 물론 버퍼는 원형입니다.
샘플 코드의 부족으로 아이디어가 모호해지지 않기를 바랍니다.
SOKS
코드를 컴파일 및 링크할 때 -pg
플래그를 사용하고 실행 파일을 실행합니다. 이 프로그램이 실행되는 동안 프로파일링 데이터는 .out 파일에 수집됩니다.
두 가지 다른 유형의 프로파일링이 있습니다.
1- 플랫 프로파일링:
gprog --flat-profile a.out
명령을 실행하여 다음 데이터를 얻었습니다.
- 기능에 소요된 전체 시간의 백분율,
- 함수에 몇 초가 소요되었는지 - 하위 함수에 대한 호출 포함 및 제외,
- 통화 횟수,
- 통화당 평균 시간.
2- 그래프 프로파일링
다음을 포함하는 각 함수에 대해 다음 데이터를 얻으려면 gprof --graph a.out
명령을 사용하십시오.
- 각 섹션에서 하나의 기능에 인덱스 번호가 표시됩니다.
- 위 함수 에는 함수 를 호출 하는 함수 의 목록 이 있습니다 .
- 함수 아래에는 해당 함수에서 호출되는 함수 목록이 있습니다.
더 많은 정보를 얻으려면 https://sourceware.org/binutils/docs-2.32/gprof/에서 볼 수 있습니다.
Pejvak
디버깅 소프트웨어 를 사용하여 코드가 느리게 실행되는 위치를 식별하는 방법은 무엇입니까?
움직이는 동안 장애물이 있다고 생각하면 속도가 감소합니다.
원치 않는 재할당의 반복, 버퍼 오버플로, 검색, 메모리 누수 등의 작업은 더 많은 실행 전력을 소비하므로 코드 성능에 부정적인 영향을 미치므로 프로파일링하기 전에 컴파일에 -pg를 추가해야 합니다.
컴파일러에 따라 g++ your_prg.cpp -pg
또는 cc my_program.cpp -g -pg
아직 시도하지 않았지만 google-perftools에 대한 좋은 소식을 들었습니다. 시도해 볼 가치가 있습니다.
valgrind --tool=callgrind ./(Your binary)
gmon.out 또는 callgrind.out.x라는 파일을 생성합니다. 그런 다음 kcachegrind 또는 디버거 도구를 사용하여 이 파일을 읽을 수 있습니다. 어떤 라인의 비용이 얼마인지와 같은 결과와 함께 사물에 대한 그래픽 분석을 제공합니다.
나도 그렇게 생각해
user10306682
아무도 Arm MAP을 언급하지 않았으므로 개인적으로 Map을 사용하여 C++ 과학 프로그램을 프로파일링하는 데 성공적으로 추가했습니다.
Arm MAP은 병렬, 다중 스레드 또는 단일 스레드 C, C++, Fortran 및 F90 코드용 프로파일러입니다. 소스 라인에 대한 심층 분석 및 병목 지점을 제공합니다. 대부분의 프로파일러와 달리 병렬 및 스레드 코드에 대해 pthread, OpenMP 또는 MPI를 프로파일링할 수 있도록 설계되었습니다.
MAP은 상용 소프트웨어입니다.
Wei
LINUX의 perf 도구에 대한 나의 경험
1. 캐시그라인드
너무 느린!
2. 지프로프
fork() 시스템 호출에서 프로파일링된 프로세스가 중단되도록 합니다.
3. 구글 CPU 프로파일러
신호를 사용하고 신호 처리기에서 특정 libunwind를 호출하기 때문에 사용할 수 없을 정도로 불안정합니다. 작동할 때 사용 가능한 뛰어난 출력. 또한 프로파일링된 프로세스가 fork() 시스템 호출에서 중단되도록 합니다.
4. 인텔 vtune 2019
포스트 프로세서가 자주 멈춥니다. 사용 가능한 출처 속성이 없습니다. 도구를 사용할 수 없습니다.
5. 네이티브 리눅스 성능
후처리 도구를 작동할 수 없어서 사용할 수 없다는 것을 알았습니다. 예를 들어 CPU 시간으로 함수를 정렬하고 호출된 함수를 포함/제외(perf-report)하는 것은 불가능합니다. CPU 시간(perf-annotate)에 기인한 소스 라인을 보는 것이 불가능하다는 것을 발견했습니다.
6. 결론
귀하의 마일리지가 다를 수 있습니다. 특히 몇 초만 실행되는 작은 실행 파일을 프로파일링하는 경우. 또한 루트 및 설치/제거 도구에 대한 권한을 갖는 것이 중요할 수 있습니다. 사용된 OS와 함께 제공되는 도구를 사용할 수 있다는 것은 중요할 수 있습니다! 특정 비네이티브 도구 세트(컴파일러, 링커 및 이미 컴파일된 라이브러리)를 사용해야 하는 경우 운이 좋지 않을 수 있습니다.
Frank Puck
출처 : http:www.stackoverflow.com/questions/375913/how-can-i-profile-c-code-running-on-linux
'etc. > StackOverFlow' 카테고리의 다른 글
java.net.URLConnection을 사용하여 HTTP 요청을 실행하고 처리하는 방법 (0) | 2021.12.20 |
---|---|
Android의 ListView에서 이미지를 지연 로드하는 방법 (0) | 2021.12.20 |
커밋을 푸시하기 위해 https 자격 증명을 캐시하는 방법이 있습니까? (0) | 2021.12.08 |
SQL Server 테이블에 열이 있는지 확인하는 방법은 무엇입니까? (0) | 2021.12.08 |
특정 문자열을 포함하는 모든 행을 텍스트 파일에서 삭제하는 방법은 무엇입니까? (0) | 2021.12.08 |