Profilage de code sous Linux
gprof
Description
Il s'agit d'un programme de profilage pour des codes en C/C++.
Utilisation
- compiler le code avec l'option [ -pg ], linker avec l'option [ -p ]
- lancer le programme, qui va normalement créer un fichier appelé gmon.out
- taper : gprof [nom_du_programme] gmon.out > profil.txt
On se retrouve alors avec un fichier texte (profil.txt) dont la syntaxe ressemble à ceci :
Profile plat: Chaque échantillon dénombre 0.01 seconds. % cumulatif auto auto total temps seconds seconds appels s/appel s/appel nom 13.72 1.62 1.62 MatSetValues_SeqAIJ(_p_Mat*, int, int const*, int, int const*, double const*, InsertMode) 4.23 2.12 0.50 412564 0.00 0.00 Llist<Phys_Elem*, Compare_Elem>::get(Phys_Elem*&) const 3.26 2.51 0.39 1374974 0.00 0.00 Compare_Elem::equal(Phys_Elem const*, Phys_Elem const*) 3.13 2.88 0.37 3184640 0.00 0.00 Phys_Elem::get_elem_id() const 2.71 3.20 0.32 25501 0.00 0.00 FEP_Meca::calc_element_matrix_2(Mymatrix<double>&, Positions&, Myvector<double>&, Field<double>*) 2.62 3.51 0.31 7 0.04 0.35 Field<double>::print_2D_slice_gmsh(FE_Mesh&, GE_Plane&, Physical_Region const&, std::string) 2.37 3.79 0.28 1 0.28 2.15 FEP_Meca::fill_system(Field<double>*, Field<double>*, Field<double>*, double, double) 2.37 4.07 0.28 4765233 0.00 0.00 Point::z() const 2.29 4.34 0.27 3682784 0.00 0.00 Phys_Elem::get_part_elem_id() const 2.24 4.60 0.27 1989078 0.00 0.00 Real_Tensor::dot(Real_Tensor const&) const 2.12 4.85 0.25 7335450 0.00 0.00 Phys_Elem::get_region_id() const [...]
C'est très convivial. Il y a moyen de déchiffrer le fichier, en tout cas de déterminer les quelques fonctions les plus gourmandes en temps de calcul, mais ça devient vite éprouvant. Il existe une interface graphique appelée Gprof2Dot qui crée des graphes beaucoup plus lisibles à partir du fichier de sortie de gprof (entre autres). J'ai peu testé cette interface parce que je ne suis arrivé à créer de graphes que pour de très petits programmes. Metafor, je n'ai même pas tenté. Il y a peut-être moyen d'en tirer quelque chose en jouant avec les options.
Références
valgrind
Description
Il s'agit en fait d'une suite d'outils pour détecter des problèmes de mémoire, comme des fuites ou des accès invalides, ou réaliser le profilage d'un code à l'aide de différentes méthodes. L'outil que j'utilise pour le profilage est callgrind, qui permet de visualiser le résultat du profilage avec une interface graphique, kcachegrind.
Utilisation
- compiler avec l'option [ -g ]. On peut profiler le code optimisé [ -g -O2 ]; le résultat est bien sûr plus utile, mais je pense qu'on perd une partie des infos. A vérifier.
- taper la commande : valgrind –tool=callgrind –dump-instr=yes –simulate-cache=yes –collect-jumps=yes [programme] [arguments]
- un fichier callgrind.out.[ID] est alors créé, où [ID] est l'identifiant du programme (celui qu'on voit avec les commandes top ou ps).
- pour visualiser le graphe, taper (si l'ID est 7388) : kcachegrind callgrind.out.7388
Le résultat est assez bordélique, il y a une foule d'informations regroupées dans les onglets, les menus, le graphe, c'est clickable de partout. Mais au moins c'est visuel. On voit clairement ici, par exemple, que le solver Skyline me prend 49% du temps :
Références
pgprof
Description
Il semble que ce soit l'équivalent de gprof pour les codes parallélisés avec OpenMP et MPI, avec en plus une interface graphique. Je n'ai pas encore testé.
Références
scalasca
Description
C'est un logiciel open-source pour le profilage de codes parallélisés avec OpenMP et MPI (officiellement Scalable Performance Analysis of Large-Scale Applications), avec interface graphique. Pas encore testé.
Références
cProfile
Description
cProfile est un module Python pour le profilage, utilisé en combinaison avec le module pstats.
Utilisation
Voici un exemple de profilage de la fonction qui charge les modèles dans Metafor:
import cProfile, pstats cProfile.run('load(\'/home/geoffrey/APC/Calc/Lug/lug3d_8c.py\')', 'profil1') r1 = pstats.Stats('profil1') r1.sort_stats('cumulative').print_stats(20)
Le résultat est assez semblable à la sortie de gprof, c'est à dire assez sobre, je dirais presque austère :
Thu Sep 2 17:12:12 2010 profil1 4045151 function calls in 21.459 CPU seconds Ordered by: cumulative time List reduced from 237 to 20 due to restriction <20> ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 21.460 21.460 /home/geoffrey/Metafor/Devel/oo_meta/toolbox/utilities.py:60(load) 1 0.005 0.005 21.459 21.459 /home/geoffrey/APC/Calc/Lug/lug3d_8c.py:5(<module>) 1 0.075 0.075 21.243 21.243 /home/geoffrey/Metafor/Devel/oo_meta/toolbox/gmsh.py:26(execute) 1 3.546 3.546 21.158 21.158 /home/geoffrey/Metafor/Devel/oo_meta/toolbox/gmsh.py:53(__loadMSH) 94888 14.588 0.000 14.588 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtGeo.py:4953(define) 944646 1.332 0.000 1.332 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtGeo.py:2161(__call__) 106834 0.622 0.000 0.622 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtGeo.py:5006(define) 191666 0.222 0.000 0.222 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtGeo.py:1510(addMeshPoint) 201721 0.216 0.000 0.216 0.000 {method 'split' of 'str' objects} 1 0.000 0.000 0.184 0.184 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtViz.py:209(__init__) 1 0.184 0.184 0.184 0.184 {_mtViz.new_VizWin} 201726 0.181 0.000 0.181 0.000 {method 'readline' of 'file' objects} 189780 0.138 0.000 0.138 0.000 {range} 752976 0.134 0.000 0.134 0.000 {method 'add' of 'set' objects} 1051480 0.126 0.000 0.126 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtGeo.py:3418(<lambda>) 213670 0.034 0.000 0.034 0.000 {method 'append' of 'list' objects} 1 0.021 0.021 0.021 0.021 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtViz.py:239(add) 94893 0.019 0.000 0.019 0.000 {len} 40 0.000 0.000 0.005 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/__init__.py:81(write) 40 0.005 0.000 0.005 0.000 /home/geoffrey/Metafor/Devel/oo_meta/wrap/mtViz.py:329(sendStringToCPP)