Vectorisation pour accélérer le code
Remplacez les boucles explicites par des opérations vectorisées pour accélérer considérablement le code.
Vectorisation pour accélérer le code est une leçon R Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage R Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours R Academy comprend 4 leçons au total.
Pourquoi la vectorisation est importante
R est un langage interprété : les boucles for entraînent donc une surcharge à chaque itération — distribution des appels de fonction, vérification des limites et coercition des types. Les opérations vectorisées déportent ce travail dans du code C compilé, qui s’exécute beaucoup plus rapidement.
La vectorisation est l’optimisation la plus efficace disponible dans R de base.
Exemple : boucle et cumsum()
Le calcul d’un total cumulatif avec une boucle for comparé à la fonction intégrée cumsum() montre clairement l’écart. cumsum() appelle du code compilé au niveau C et traite tout le vecteur en un seul parcours.
n <- 500000
x <- rnorm(n)
t_loop <- system.time({
result <- numeric(n)
result[1] <- x[1]
for (i in 2:n) result[i] <- result[i-1] + x[i]
})['elapsed']
t_vec <- system.time({
result2 <- cumsum(x)
})['elapsed']
cat('Loop :', t_loop, 's
')
cat('cumsum:', t_vec, 's
')ifelse() contre for + if
ifelse(condition, yes, no) est une condition vectorisée qui évalue la condition sur tout un vecteur à la fois. Elle remplace les boucles for + if élément par élément par un seul parcours au niveau C.
n <- 300000
x <- rnorm(n)
t_loop <- system.time({
result <- numeric(n)
for (i in seq_len(n)) result[i] <- if (x[i] > 0) x[i] else -x[i]
})['elapsed']
t_vec <- system.time({
result2 <- ifelse(x > 0, x, -x)
})['elapsed']
cat('for+if :', t_loop, 's
')
cat('ifelse :', t_vec, 's
')Préallouer les vecteurs de résultats
Lorsqu’une boucle est inévitable, préallouez le vecteur de résultats avant la boucle. Agrandir un vecteur avec c(result, new_val) dans une boucle recopie tout le vecteur à chaque itération — soit O(n^2) opérations mémoire au total.
n <- 20000
t_grow <- system.time({
result <- c()
for (i in seq_len(n)) result <- c(result, i^2)
})['elapsed']
t_prealloc <- system.time({
result2 <- numeric(n)
for (i in seq_len(n)) result2[i] <- i^2
})['elapsed']
cat('Growing vector:', t_grow, 's
')
cat('Pre-allocated :', t_prealloc, 's
')Choisir le bon type lors de la préallocation
Utilisez le constructeur typé correspondant à vos données afin d’éviter toute coercition implicite lors de la préallocation :
numeric(n)— nombres flottants en double précisioninteger(n)— nombres entierscharacter(n)— chaînes videslogical(n)— valeurs FALSEvector('list', n)— liste de NULL
n <- 5
cat('numeric :', numeric(n), '
')
cat('integer :', integer(n), '
')
cat('logical :', logical(n), '
')
cat('character:', character(n), '
')
cat('list len :', length(vector('list', n)), '
')colSums() et rowSums() contre apply()
Pour les opérations sur les matrices, colSums(m), rowSums(m), colMeans(m) et rowMeans(m) sont des routines C fortement optimisées. Elles sont systématiquement plus rapides que apply(m, 1, sum), qui distribue la fonction R sum une fois par ligne.
m <- matrix(rnorm(1000 * 2000), nrow = 1000)
t_apply <- system.time(apply(m, 2, sum))['elapsed']
t_colsums <- system.time(colSums(m))['elapsed']
cat('apply(m,2,sum):', t_apply, 's
')
cat('colSums(m) :', t_colsums, 's
')L’arithmétique vectorisée est toujours rapide
Les opérations arithmétiques de base sur les vecteurs — +, -, *, /, ^, sqrt(), log(), exp() — sont toutes vectorisées. Elles s’effectuent élément par élément sur tout un vecteur en un seul appel C. Préférez-les toujours aux boucles.
x <- 1:1000000
t1 <- system.time(y <- x^2 + 2*x + 1)['elapsed']
t2 <- system.time({
y2 <- numeric(length(x))
for (i in seq_along(x)) y2[i] <- x[i]^2 + 2*x[i] + 1
})['elapsed']
cat('Vectorized:', t1, 's
')
cat('Loop :', t2, 's
')Sous-ensembles logiques plutôt que boucles
Filtrer un vecteur avec une condition logique est une opération vectorisée. Au lieu de parcourir le vecteur et d’ajouter des éléments selon une condition, créez un indice logique et effectuez une seule sélection : le code C sous-jacent parcourt les données une seule fois.
x <- rnorm(500000)
t_loop <- system.time({
pos <- c()
for (v in x) if (v > 0) pos <- c(pos, v)
})['elapsed']
t_vec <- system.time({
pos2 <- x[x > 0]
})['elapsed']
cat('Loop filter:', t_loop, 's
')
cat('Logical idx:', t_vec, 's
')which() et tabulate() pour travailler avec les indices
Lorsque vous avez besoin des positions des valeurs TRUE, which(condition) est vectorisé et rapide. tabulate(bin_vector) compte les occurrences entières plus rapidement que table() pour les plages d’entiers denses.
x <- sample(1:10, 100000, replace = TRUE)
t_table <- system.time(table(x))['elapsed']
t_tabulate <- system.time(tabulate(x, nbins = 10))['elapsed']
cat('table() :', t_table, 's
')
cat('tabulate():', t_tabulate, 's
')
idx <- which(x == 5)
cat('Positions of 5: first 5 =', head(idx, 5), '
')Quand les boucles restent acceptables
Toutes les boucles ne sont pas mauvaises. Les boucles sont acceptables lorsque :
- Chaque itération dépend du résultat précédent (dépendance séquentielle)
- Le nombre d’itérations est faible (< 1000)
- Le corps de la boucle appelle une fonction complexe sans équivalent vectorisé
Dans ces cas, concentrez-vous sur la préallocation et évitez d’agrandir des structures à l’intérieur de la boucle.
# Sequential dependency -- loop is correct here
fib <- function(n) {
result <- integer(n)
result[1] <- 1L
if (n >= 2) result[2] <- 1L
for (i in seq_len(n)[-c(1,2)]) result[i] <- result[i-1] + result[i-2]
result
}
cat('Fibonacci:', fib(10), '
')Résumé de la vectorisation
Règles essentielles pour vectoriser du code R rapide :
- Utilisez
cumsum/cumprod/diffpour les accumulations séquentielles - Utilisez
ifelse()pour les conditions appliquées élément par élément - Préallouez avec
numeric(n)/vector('list',n) - Utilisez
colSums/rowSums/colMeans/rowMeansplutôt queapply() - La sélection logique est préférable aux boucles de filtrage
Vérification rapide : préallocation
Pourquoi l’agrandissement d’un vecteur avec result <- c(result, new_val) à l’intérieur d’une boucle est-il si lent pour une grande valeur de n ?
Récapitulatif de la vectorisation
La vectorisation est le principal levier de performance de R :
- Les fonctions vectorisées (
cumsum,ifelse, opérateurs arithmétiques) appellent du code C compilé : elles sont 10 à 100 fois plus rapides que les boucles R équivalentes - Préallouez les conteneurs de résultats avant toute boucle inévitable afin d’éviter des copies en O(n2)
colSums/rowSumsest plus rapide queapply()pour agréger des matrices- La sélection logique remplace proprement et rapidement les boucles de filtrage
Questions Fréquemment Posées
La leçon « Vectorisation pour accélérer le code » est-elle gratuite ?
Oui — le texte complet de « Vectorisation pour accélérer le code » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours R Academy, passe à CoddyKit PRO. Le cours R Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Vectorisation pour accélérer le code » ?
Remplacez les boucles explicites par des opérations vectorisées pour accélérer considérablement le code. Tu pratiques R Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer R Academy ?
Aucune expérience préalable n'est requise. R Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Vectorisation pour accélérer le code » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon R Academy ?
Oui. Chaque leçon R Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- system.time() et proc.time()
- Profiler du code avec Rprof et profvis
- Vectorisation pour accélérer le code
- Évaluer les performances avec microbenchmark