Paquet parallel et detectCores()
Lancez des grappes dérivées ou à sockets et répartissez le travail entre les cœurs du CPU.
Paquet parallel et detectCores() est une leçon R Academy gratuite sur CoddyKit. Ceci est la leçon 1 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 l’informatique parallèle ?
Les ordinateurs modernes disposent de plusieurs cœurs CPU. Par défaut, R s’exécute sur un seul cœur et laisse les autres inactifs. Le paquet parallel (intégré à R) vous permet d’exploiter tous les cœurs afin d’accélérer les calculs répétitifs.
# Check how many cores your machine has
library(parallel)
total_cores <- detectCores()
logical_cores <- detectCores(logical = TRUE)
physical_cores <- detectCores(logical = FALSE)
cat('Total logical cores:', total_cores, '
')
cat('Physical cores:', physical_cores, '
')makeCluster et stopCluster
makeCluster(n) crée n processus de travail. Appelez toujours stopCluster(cl) lorsque vous avez terminé afin de libérer les ressources. Une convention courante consiste à utiliser detectCores() - 1 pour laisser un cœur disponible pour l’OS.
library(parallel)
# Spawn workers (leave 1 core for system)
n_cores <- detectCores() - 1
cl <- makeCluster(n_cores)
cat('Cluster created with', n_cores, 'workers\n')
# Always clean up!
stopCluster(cl)
cat('Cluster stopped.\n')clusterExport : partager des variables
Les processus de travail disposent de leur propre espace mémoire et ne peuvent pas accéder à votre environnement global. Utilisez clusterExport(cl, varlist) pour copier les objets nommés du processus maître vers tous les processus de travail.
library(parallel)
cl <- makeCluster(2)
# Define a variable and a function in the master
base_value <- 100
add_base <- function(x) x + base_value
# Export them to workers
clusterExport(cl, varlist = c('base_value', 'add_base'))
# Now workers can use them
result <- parLapply(cl, 1:4, function(x) add_base(x))
cat(unlist(result), '\n') # 101 102 103 104
stopCluster(cl)clusterEvalQ : exécuter le code de configuration
clusterEvalQ(cl, expr) évalue une expression sur chaque processus de travail — ce qui est utile pour charger des paquets ou importer des fichiers auxiliaires sur tous les nœuds avant le début du calcul principal.
library(parallel)
cl <- makeCluster(2)
# Load a package on every worker
clusterEvalQ(cl, {
library(stats)
set.seed(42) # set seed per worker
})
# Each worker can now use stats functions
result <- parLapply(cl, 1:4, function(n) rnorm(n, mean = 0, sd = 1))
result[[1]] # one random normal value
stopCluster(cl)parLapply : lapply en parallèle
parLapply(cl, X, FUN) est l’équivalent parallèle de lapply(). Il répartit les éléments de X entre les processus de travail et rassemble les résultats sous forme de liste. Il fonctionne sur toutes les plateformes (Windows, macOS, Linux).
library(parallel)
cl <- makeCluster(2)
# Simulate slow computation: sleep 0.1s per item
clusterEvalQ(cl, Sys.sleep)
slow_square <- function(x) {
Sys.sleep(0.05)
x^2
}
clusterExport(cl, 'slow_square')
system.time(
result <- parLapply(cl, 1:8, slow_square)
)
cat(unlist(result), '\n') # 1 4 9 16 25 36 49 64
stopCluster(cl)parSapply : résultats simplifiés
parSapply(cl, X, FUN) est la version parallèle de sapply(). Il simplifie automatiquement le résultat en vecteur ou en matrice lorsque cela est possible, ce qui le rend pratique lorsque votre fonction renvoie une valeur scalaire.
library(parallel)
cl <- makeCluster(2)
# parSapply returns a simplified vector
squares <- parSapply(cl, 1:10, function(x) x^2)
cat(squares, '\n') # 1 4 9 16 25 36 49 64 81 100
# Returns a matrix if FUN returns a vector of same length
stats_result <- parSapply(cl, 1:4, function(n) {
x <- rnorm(100)
c(mean = mean(x), sd = sd(x))
})
print(stats_result) # 2x4 matrix
stopCluster(cl)mclapply : parallélisme par duplication de processus
mclapply() utilise la duplication par embranchement : il copie le processus R actuel au lieu d’en créer de nouveaux, ce qui accélère le démarrage et donne aux processus de travail un accès implicite à l’environnement parent. Cependant, il ne fonctionne que sous Unix/macOS, pas sous Windows.
library(parallel)
# mclapply: Unix/macOS only
# Workers inherit the parent environment automatically
base_value <- 42
if (.Platform$OS.type != 'windows') {
result <- mclapply(
1:8,
function(x) x * base_value, # base_value visible without export
mc.cores = 4
)
cat(unlist(result), '\n')
} else {
cat('mclapply not supported on Windows. Use parLapply instead.\n')
}Comparer les performances séquentielles et parallèles
Le parallélisme entraîne un surcoût : le démarrage du groupe de processus, la sérialisation des données et la communication entre processus prennent tous du temps. Il n’est avantageux que lorsque le calcul de chaque élément est suffisamment coûteux pour compenser ce surcoût.
library(parallel)
cl <- makeCluster(2)
# Task: compute 100 iterations of matrix multiply
heavy_task <- function(n) {
m <- matrix(rnorm(200), nrow = 100)
sum(m %*% t(m))
}
clusterExport(cl, 'heavy_task')
seq_time <- system.time(lapply(1:20, heavy_task))[['elapsed']]
par_time <- system.time(parLapply(cl, 1:20, heavy_task))[['elapsed']]
cat('Sequential:', round(seq_time, 3), 's\n')
cat('Parallel: ', round(par_time, 3), 's\n')
cat('Speedup: ', round(seq_time / par_time, 2), 'x\n')
stopCluster(cl)Initialiser le RNG en parallèle
La génération de nombres aléatoires en parallèle est délicate : chaque processus de travail a besoin d’un flux indépendant et reproductible. Utilisez clusterSetRNGStream(cl, seed) avec le générateur L'Ecuyer-CMRG pour obtenir une génération aléatoire parallèle reproductible.
library(parallel)
cl <- makeCluster(2)
# Set reproducible RNG streams across workers
clusterSetRNGStream(cl, iseed = 123)
# Each worker uses its own independent random stream
results1 <- parSapply(cl, 1:6, function(i) rnorm(1))
# Reset and repeat — same results
clusterSetRNGStream(cl, iseed = 123)
results2 <- parSapply(cl, 1:6, function(i) rnorm(1))
cat('Run 1:', round(results1, 4), '\n')
cat('Run 2:', round(results2, 4), '\n')
cat('Identical:', identical(results1, results2), '\n')
stopCluster(cl)Gérer les erreurs dans les groupes de processus
Si un processus de travail déclenche une erreur, parLapply() la relance dans le processus maître. Encapsulez les appels dans tryCatch() à l’intérieur de la fonction, ou utilisez tryCatch() autour de l’appel parLapply() entier pour gérer les échecs correctement.
library(parallel)
cl <- makeCluster(2)
# Wrap risky code inside the worker function
safe_log <- function(x) {
tryCatch(
log(x),
warning = function(w) NA_real_,
error = function(e) NA_real_
)
}
clusterExport(cl, 'safe_log')
# -1 produces NaN warning, 'a' produces an error
input <- list(4, 9, -1, 'a', 16)
result <- parLapply(cl, input, safe_log)
cat(unlist(result), '\n') # 1.386 2.197 NaN NA 2.773
stopCluster(cl)Modèle pratique de parallélisme
Voici un flux de travail parallèle complet et idiomatique : détecter le nombre de cœurs, créer le groupe de processus, exporter les dépendances, exécuter le calcul, rassembler les résultats et toujours arrêter le groupe — même en cas d’erreur — avec on.exit().
library(parallel)
run_parallel <- function(data, fn, n_workers = detectCores() - 1) {
cl <- makeCluster(n_workers)
on.exit(stopCluster(cl)) # guaranteed cleanup
clusterExport(cl, 'fn', envir = environment())
result <- parLapply(cl, data, fn)
result
}
# Example: bootstrap mean estimation
samples <- lapply(1:100, function(i) rnorm(50, mean = 5, sd = 2))
means <- run_parallel(samples, mean)
cat('Grand mean:', round(mean(unlist(means)), 3), '\n')
cat('95% CI: [',
round(quantile(unlist(means), 0.025), 3), ',',
round(quantile(unlist(means), 0.975), 3), ']\n')Vérification rapide
Quelle fonction devez-vous utiliser pour garantir que stopCluster(cl) sera appelé même si une erreur se produit dans votre code parallèle ?
Récapitulatif : paquet parallel
À retenir :
detectCores()indique le nombre de cœurs disponibles ; utilisezdetectCores() - 1pour définir la taille du groupemakeCluster(n)/stopCluster(cl)gèrent le cycle de vie des processus de travailclusterExport()copie les objets ;clusterEvalQ()exécute le code de configuration sur les processus de travailparLapply()/parSapply()sont des itérateurs parallèles compatibles avec plusieurs plateformesmclapply()est réservé à Unix, mais son démarrage est plus rapide grâce à la duplication de processus- Utilisez
on.exit(stopCluster(cl))pour garantir le nettoyage - Le parallélisme n’est avantageux que pour les tâches nécessitant beaucoup de calculs
# Minimal reproducible parallel pattern
library(parallel)
cl <- makeCluster(max(1, detectCores() - 1))
on.exit(stopCluster(cl))
clusterSetRNGStream(cl, iseed = 42)
result <- parSapply(cl, 1:8, function(x) x^2 + rnorm(1, 0, 0.1))
cat(round(result, 2), '\n')Questions Fréquemment Posées
La leçon « Paquet parallel et detectCores() » est-elle gratuite ?
Oui — le texte complet de « Paquet parallel et detectCores() » 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 « Paquet parallel et detectCores() » ?
Lancez des grappes dérivées ou à sockets et répartissez le travail entre les cœurs du CPU. 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 1 sur 4.
Combien de temps prend la leçon « Paquet parallel et detectCores() » ?
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
- Paquet parallel et detectCores()
- Le cadriciel future
- furrr : opérations parallèles avec purrr
- Déboguer et équilibrer la charge du code parallèle