Chapitre 4 Profiler son code

On parle de profiling en anglais. Il s’agit de déterminer ce qui prend du temps dans un code. Le but étant une fois trouvé le bloc de code qui prend le plus de temps dans l’exécution d’optimiser uniquement cette brique.

Pour obtenir un profiling du code ci-dessous, sélectionner les lignes de code d’intérêt et aller dans le menu “Profile” puis “Profile Selected Lines” (ou Ctrl+Alt+Shift P).

n <- 10e4
pdfval <- mvnpdf(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE)

OK, we get it ! Concaténer un vecteur au fur et à mesure dans une boucle n’est vraiment pas une bonne idée.

4.1 Comparaison avec une version plus habile de mnvpdf()

Considérons une nouvelle version de mvnpdf(), appelée mvnpdfsmart(). Télécharger le fichier puis l’inclure dans le package.

Profiler la commande suivante :

n <- 10e4
pdfval <- mvnpdfsmart(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE)

On a effectivement résolu le problème et on apprend maintenant de manière plus fine ce qui prend du temps dans notre fonction.

Pour confirmer que mvnpdfsmart() est effectivement bien plus rapide que mvnpdf() on peut re-faire une comparaison avec microbenchmark() :

n <- 1000
mb <- microbenchmark(mvnpdf(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     mvnpdfsmart(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     times=100L)
mb
## Unit: milliseconds
##                                                            expr      min
##       mvnpdf(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 4.571270
##  mvnpdfsmart(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 3.291484
##        lq     mean   median        uq      max neval
##  6.302558 9.442151 7.567892 11.362984 35.86973   100
##  3.942799 5.996547 4.820625  6.667599 26.72489   100
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.

Et on peut également voir si on devient compétitif avec dmvnorm() :

n <- 1000
mb <- microbenchmark(mvtnorm::dmvnorm(matrix(1.96, nrow = n, ncol = 2)),
                     mvnpdf(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     mvnpdfsmart(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     times=100L)
mb
## Unit: microseconds
##                                                            expr      min
##              mvtnorm::dmvnorm(matrix(1.96, nrow = n, ncol = 2))   64.809
##       mvnpdf(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 4237.122
##  mvnpdfsmart(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 3318.527
##        lq       mean   median        uq       max neval
##   104.291   220.5934  139.768   213.964  1039.216   100
##  5140.069 10256.0230 6519.999 14731.044 34242.538   100
##  3838.899  6969.0440 4952.510 10348.500 18892.306   100
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.

Il y a encore du travail…

4.2 Comparaison avec une version optimisée dans R

Boris est arrivée après plusieurs recherches et tests à une version optimisée avec les outils de R.

Inclure la fonction mvnpdfoptim() dans le package, puis profiler cette fonction :

n <- 10e4
pdfval <- mvnpdfoptim(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE)

Et un petit microbenchmark() :

n <- 1000
mb <- microbenchmark(mvtnorm::dmvnorm(matrix(1.96, nrow = n, ncol = 2)),
                     mvnpdf(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     mvnpdfsmart(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     mvnpdfoptim(x=matrix(1.96, nrow = 2, ncol = n), Log=FALSE),
                     times=100L)
mb
## Unit: microseconds
##                                                            expr      min
##              mvtnorm::dmvnorm(matrix(1.96, nrow = n, ncol = 2))   73.215
##       mvnpdf(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 4882.105
##  mvnpdfsmart(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 3265.964
##  mvnpdfoptim(x = matrix(1.96, nrow = 2, ncol = n), Log = FALSE) 2758.766
##        lq      mean   median        uq      max neval
##   100.802  314.2754  125.243  160.5135 12841.85   100
##  5329.044 8329.3259 6125.202 9463.3200 41610.03   100
##  3868.067 5869.9909 4164.388 5837.1180 38389.15   100
##  3086.011 5073.3297 3300.896 5834.8805 18534.30   100
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.

Pour finir on peut profiler la fonction dmvnorm() :

n <- 10e5
pdfval <- mvtnorm::dmvnorm(matrix(1.96, nrow = n, ncol = 2))