개발관련/Linux

Linux에서 실행되는 C ++ 코드를 프로파일링 하는 방법

Rateye 2021. 6. 29. 10:14
728x90
반응형

 

질문 : Linux에서 실행되는 C ++ 코드를 어떻게 프로파일링 할 수 있습니까?

Linux에서 실행중인 C ++ 응용 프로그램이 있는데,이 응용 프로그램을 최적화하는 중입니다. 내 코드의 어떤 영역이 느리게 실행되고 있는지 어떻게 알 수 있습니까?

답변

프로파일 러를 사용하는 것이 목표 인 경우 제안 된 것 중 하나를 사용하십시오.

그러나 서두르고 주관적으로 느리면서 디버거에서 프로그램을 수동으로 중단 할 수있는 경우 성능 문제를 찾는 간단한 방법이 있습니다.

여러 번 중지하고 매번 호출 스택을 확인하십시오. 시간의 일정 비율, 20 % 또는 50 % 등을 낭비하는 코드가 있다면 각 샘플에 대한 작업에서 코드를 포착 할 확률입니다. 따라서 그것은 대략적으로 볼 수있는 샘플의 비율입니다. 교육받은 추측이 필요하지 않습니다. 문제가 무엇인지 추측 할 수 있다면이를 증명하거나 반증 할 것입니다.

크기가 다른 여러 성능 문제가있을 수 있습니다. 그중 하나를 정리하면 나머지는 다음 패스에서 더 많은 비율을 차지하고 더 쉽게 찾을 수 있습니다. 이 확대 효과 는 여러 문제에 걸쳐 복합적으로 작용할 때 정말 엄청난 속도 향상 요인으로 이어질 수 있습니다.

주의 사항 : 프로그래머는 직접 사용하지 않는 한이 기술에 회의적인 경향이 있습니다. 프로파일 러가이 정보를 제공한다고 말하지만 전체 호출 스택을 샘플링 한 다음 무작위 샘플 세트를 검사 할 수있는 경우에만 해당됩니다. (요약은 통찰력을 잃는 곳입니다.) 호출 그래프는 동일한 정보를 제공하지 않습니다.

그들은 또한 실제로 어떤 프로그램에서든 작동 할 때 장난감 프로그램에서만 작동한다고 말할 것이며, 더 큰 프로그램에서 더 잘 작동하는 것 같습니다. 그들은 때때로 문제가 아닌 것을 발견한다고 말할 것입니다. 그러나 그것은 당신이 무언가를 한 번 볼 때만 사실입니다. 두 개 이상의 샘플에서 문제가 발견되면 실제입니다.

PS 이것은 Java 에서처럼 특정 시점에 스레드 풀의 호출 스택 샘플을 수집하는 방법이있는 경우 다중 스레드 프로그램에서도 수행 할 수 있습니다.

PPS 일반적으로 소프트웨어에 추상화 계층이 많을수록 이것이 성능 문제 (그리고 속도 향상의 기회)의 원인이라는 것을 알 가능성이 높습니다.

추가됨 : 명확하지 않을 수 있지만 스택 샘플링 기술은 재귀가있을 때 똑같이 잘 작동합니다. 그 이유는 명령어 제거로 절약되는 시간이 샘플 내에서 발생할 수있는 횟수에 관계없이 명령어를 포함하는 샘플의 비율에 의해 근사화되기 때문입니다.

내가 자주 듣는 또 다른 이의는 " 어딘가에서 무작위로 멈출 것이고 실제 문제를 놓칠 것입니다 "입니다. 이것은 실제 문제가 무엇인지에 대한 사전 개념을 가지고 있기 때문입니다. 성능 문제의 핵심 속성은 기대에 어긋난다는 것입니다. 샘플링은 문제가 있음을 알려주고 첫 번째 반응은 불신입니다. 그것은 당연한 일이지만 문제가 발견되면 그것이 진짜이고 그 반대의 경우도 마찬가지라고 확신 할 수 있습니다.

추가 : 어떻게 작동하는지 베이지안 설명을하겠습니다. 일부 명령 I (호출 또는 기타)가 호출 스택 f (따라서 비용이 많이 듭니다)가 있다고 가정합니다. 간단하게하기 위해 f 가 무엇인지 모르지만 0.1, 0.2, 0.3, ... 0.9, 1.0 중 하나라고 가정하고 이러한 각 가능성의 사전 확률은 0.1이므로 이러한 모든 비용은 동일합니다. a-priori.

그런 다음 스택 샘플을 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) 는 이전 가정 인 0.6 %에서 26 %라고합니다. I 의 가능한 비용 추정치를 업데이트 할 수 있도록합니다. 데이터의 양이 적 으면 비용이 얼마인지 정확하게 알려주지 않고 고칠 가치가있을만큼 충분히 크다는 것입니다.

그것을 보는 또 다른 방법은 승계 의 법칙입니다. 동전을 두 번 던지고 두 번 앞면이 나오면 동전의 가중치에 대해 무엇을 알 수 있습니까? 대답하는 존경받는 방법은 평균값 (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 %입니다.

다음은 측정 검사와 스택 샘플 검사의 차이점에 대한 간단한 그림입니다. 병목 현상은 이와 같은 하나의 큰 덩어리 일 수도 있고 여러 개의 작은 덩어리 일 수도 있지만 아무런 차이가 없습니다.

여기에 이미지 설명 입력

측정은 수평입니다. 특정 루틴에 걸리는 시간을 알려줍니다. 샘플링은 수직입니다. 그 순간 전체 프로그램이하는 일을 피할 수있는 방법이 있고 두 번째 샘플 에서 그것을 본다면 병목 현상을 발견 한 것입니다. 그것이 차이를 만드는 것입니다-얼마나 많은 시간을 소비하는지가 아니라 시간을 소비하는 모든 이유를 보는 것입니다.

출처 : https://stackoverflow.com/questions/375913/how-can-i-profile-c-code-running-on-linux
728x90
반응형