2122 votes

Que puis-je utiliser pour le profil de code C++ sous Linux?

J'ai une application C++, je suis dans le processus d'optimisation. Quel outil puis-je utiliser pour déterminer mon ralentit le code?

1596voto

Mike Dunlavey Points 25419

Si votre objectif est d'utiliser un profiler, utilisez l'une des suggestions.

Toutefois, si vous êtes pressé et vous pouvez manuellement interrompre votre programme sous le débogueur alors qu'il est subjectivement lent, il y a un moyen simple de trouver des problèmes de performances.

Juste arrêter plusieurs fois, et à chaque fois regarder la pile d'appel. Si il y a un code qui est perdre un certain pourcentage de l'heure, 20% ou 50% ou que ce soit, qui est la probabilité que vous l'attraper dans l'acte sur chaque échantillon. Donc, c'est approximativement le pourcentage d'échantillons sur lequel vous allez le voir. Il n'y a aucune conjecture instruite nécessaire. Si vous avez une conjecture quant à ce qui est le problème, ce sera à prouver ou à réfuter.

Vous pouvez avoir de multiples problèmes de performances de différentes tailles. Si vous nettoyez l'un d'eux, le reste prendra un pourcentage plus élevé, et être plus facile à repérer, sur des passes suivantes.

Mise en garde: les programmeurs ont tendance à être sceptique à propos de cette technique, sauf s'ils ont utilisé eux-mêmes. Ils diront que les profileurs de vous donner cette information, mais cela n'est vrai que si ils sont représentatifs de l'ensemble de la pile des appels. Les graphes d'appels ne vous donnent pas les mêmes informations, parce que 1) ils ne sont pas résumer au niveau de l'instruction, et 2) ils donnent à confusion résumés dans la présence de la récursivité. Ils disent aussi qu'il ne fonctionne que sur jouet programmes, alors qu'en réalité, il fonctionne sur n'importe quel programme, et il semble que cela fonctionne mieux sur les grands programmes, parce qu'ils ont tendance à avoir plus de problèmes à trouver.

P. S. Ceci peut également être fait sur multi-thread programmes si il existe un moyen de collecter de la pile des appels, des échantillons du pool de threads à un point dans le temps, comme il est en Java.

P. P. S Comme un accidenté de la généralité, le plus de couches d'abstraction que vous avez dans votre logiciel, plus vous êtes susceptible de trouver que cela est la cause des problèmes de performances (et la possibilité d'obtenir de l'accélération).

Ajouté: Il pourrait ne pas être évident, mais la pile de la technique d'échantillonnage fonctionne aussi bien en présence de la récursivité. La raison en est que le temps qui aurait pu être sauvé par la suppression d'une instruction est évaluée en fonction de la fraction des échantillons contenant, quel que soit le nombre de fois qu'il peut se produire au sein d'un échantillon.

Une autre objection que j'entends souvent est: "Il va s'arrêter à un endroit aléatoire, et il va manquer le véritable problème". Ceci vient d'avoir un concept de ce qu'est le véritable problème. Une propriété clé des problèmes de performance, c'est qu'ils défient les attentes. L'échantillonnage vous dit quelque chose est un problème, et votre première réaction est l'incrédulité. C'est naturel, mais vous pouvez être sûr s'il détecte un problème, il est réel, et vice-versa.

AJOUTÉ le: Permettez-moi de faire un Bayésienne explication de la façon dont il fonctionne. Supposons qu'il existe une certaine instruction I (appel ou autrement) qui est sur la pile d'appel d'une fraction f du temps (et donc les coûts que beaucoup). Pour des raisons de simplicité, supposons que nous ne savons pas ce qu' f , mais supposons qu'il s'agit soit 0.1, 0.2, 0.3, ... 0.9, 1.0, et l'état de la probabilité de chacune de ces possibilités est de 0,1, de sorte que la totalité de ces coûts sont tout aussi susceptibles a priori.

Ensuite, supposons que nous prenions seulement 2 échantillons de la pile, et nous voyons l'instruction I sur les deux échantillons, désigné d'observation o=2/2. Cela nous donne de nouvelles estimations de la fréquence f de I, selon ce:

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)

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                

La dernière colonne indique que, par exemple, la probabilité qu' f >= 0.5 est de 92%, passant ainsi de l'état de la supposition de 60%.

Supposons que les hypothèses préalables sont différents. Supposons que nous supposons P(f=0.1) est .991 (presque certain), et toutes les autres possibilités sont presque impossible (0.001). En d'autres termes, notre avant certitude c'est que l' I n'est pas cher. Alors nous obtenons:

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)

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                

Maintenant, il dit P(f >= 0.5) est de 26%, passant de l'état de la supposition de 0,6%. Afin de Bayes nous permet de mettre à jour notre estimation du coût probable de l' I. Si la quantité de données est petit, il ne nous dit pas exactement ce que le coût est seulement qu'il est assez grand pour être en vaut la fixation.

Encore une autre façon de voir les choses est appelé la Règle De Succession. Si vous lancez une pièce de 2 fois, et c'est pile les deux fois, ce qui fait que vous parler de la probable pondération de la pièce? Le respecté moyen de réponse est de dire que c'est une Beta, la distribution, avec une valeur moyenne (en nombre de hits + 1) / (nombre d'essais + 2) = (2+1)/(2+2) = 75%.

(La clé est que nous voyons I plus d'une fois. Si l'on ne se voit qu'une fois, cela ne nous dit pas beaucoup, sauf qu' f > 0.)

Donc, même un très petit nombre d'échantillons peut nous en dire beaucoup sur le coût des instructions qu'il voit. (Et il va voir avec une fréquence, en moyenne, proportionnelle à leur coût. Si n des échantillons sont prélevés, et f est le coût, alors I apparaîtra sur nf+/-sqrt(nf(1-f)) des échantillons. Exemple, n=10, f=0.3, c'est - 3+/-1.4 des échantillons.)

691voto

Ajay Points 3276

Vous pouvez utiliser valgrind avec les options suivantes

valgrind --tool=callgrind ./(Your binary)

Il va générer un fichier appelé callgrind.out.x. Vous pouvez ensuite utiliser kcachegrind outil pour lire ce fichier. Il vous donnera une analyse graphique des choses avec des résultats tels que les lignes de coût combien.

385voto

Nazgob Points 4548

Je suppose que vous êtes en utilisant GCC. La solution standard serait de profil avec gprof.

Assurez-vous d'ajouter -pg de la compilation avant de profilage:

cc -o myprog myprog.c utils.c -g -pg

Je n'ai pas encore essayé mais j'ai entendu de bonnes choses à propos de google-perftools. Il est certainement en valeur un essai.

Liés à la question ici.

Quelques autres mots à la mode si gprof ne pas faire le travail pour vous: Valgrind, Intel VTune, Soleil DTrace.

296voto

Will Points 30630

Les noyaux plus récents (par exemple, la dernière Ubuntu noyaux) sont livrés avec la nouvelle "perf" outils (apt-get install linux-tools) aka perf_events

Ceux-ci viennent avec classique d'échantillonnage profileurs (homme-page) ainsi que le génial timechart!

La chose importante est que ces outils peuvent être le système de profilage et pas seulement les processus de profilage - ils peuvent montrer l'interaction entre les threads, processus et le noyau, et qui vous permettra de mieux comprendre la planification et IO dépendances entre les processus.

alt text

98voto

Greg Rogers Points 18119

oprofile est bonne, car elle rend beaucoup plus facile que gprof pour le profil de plusieurs programmes à la fois. Vous pouvez également l'exécuter sur votre communiqué de construire (si il y a des symboles), au lieu d'avoir à construire un spécial de profilage de construire.

Si vous n'avez pas de soins sur la prise d'un énorme gain de performance (50x), valgrind (cachegrind) est bonne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X