Mon code est lent !

Écrire du code R efficace

Colin Gillespie

Jumping Rivers & Newcastle University

Mon code est-il vraiment lent ?

  • 1 seconde ?
  • 1 minute ?
  • 1 heure ?
Écrire du code R efficace

Mon code est-il vraiment lent ?

Écrire du code R efficace

Étalonnage (benchmark)

  1. Encapsuler la fonction à évaluer
  2. Chronométrer selon divers scénarios, p. ex. taille de l'ensemble de données
Écrire du code R efficace

Exemple : suite de nombres

$$ 1, 2, 3, \ldots, n $$

Option 1
1:n
Option 2
seq(1, n)
Option 3
seq(1, n, by = 1)
Écrire du code R efficace

Encapsuler dans une fonction

colon <- function(n) 1:n
colon(5)
1 2 3 4 5
seq_default <- function(n) seq(1, n)
seq_by <- function(n) seq(1, n, by = 1)
Écrire du code R efficace

Chronométrer avec system.time()

system.time(colon(1e8))
#   user  system elapsed
#  0.032   0.028   0.060
system.time(seq_default(1e8))
#   user  system elapsed
#  0.060   0.028   0.086
system.time(seq_by(1e8))
#   user  system elapsed
#  1.088   0.520   1.600
  • Le temps user est le temps CPU pour les instructions de l'utilisateur.
    • Le temps system est le temps CPU utilisé par le système pour le processus appelant.
    • Le temps elapsed est environ la somme des deux ; c'est généralement celui qui nous intéresse.
Écrire du code R efficace

Stocker le résultat

Le problème avec

system.time(colon(1e8))

c'est que nous n'avons pas stocké le résultat. Il faut relancer le code pour l'enregistrer :

res <- colon(1e8)

L'opérateur <- fait les deux :

  • Passage d'arguments
  • Affectation d'objet
system.time(res <- colon(1e8))

L'opérateur = fait une seule chose :

  • Passage d'arguments
  • Affectation d'objet
# Provoque une erreur
system.time(res = colon(1e8))
Écrire du code R efficace

Temps relatif

Méthode Temps absolu (s) Temps relatif
colon(n) 0.060 $0.060/0.060 = 1.00$
seq_default(n) 0.086 $0.086/0.060 = 1.40$
seq_by(n) 1.607 $1.60/0.060 = 26.7$
Écrire du code R efficace

Le paquet microbenchmark

  • Compare des fonctions
    • Chaque fonction est exécutée plusieurs fois
library("microbenchmark")

n <- 1e8 microbenchmark(colon(n), seq_default(n), seq_by(n), times = 10) # Exécuter chaque fonction 10 fois
# Unit: milliseconds
#           expr  min   lq  mean  median   uq  max neval cld
#       colon(n)   59  130   220     202  341  391    10  a
# seq_default(n)   94  204   290     337  348  383    10  a
#      seq_by(n) 1945 2044  2260    2275 2359 2787    10   b
Écrire du code R efficace

Passons à la pratique !

Écrire du code R efficace

Preparing Video For Download...