Le cadriciel future
Utilisez plan(multisession) et future() pour effectuer un traitement parallèle asynchrone et portable.
Le cadriciel future est une leçon R Academy gratuite sur CoddyKit. Ceci est la leçon 2 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.
Qu’est-ce que le package future ?
Le package future fournit une API unifiée de haut niveau pour la programmation asynchrone et parallèle en R. Un future est un emplacement réservé pour une valeur qui sera disponible ultérieurement : elle peut avoir été calculée sur un autre cœur ou une autre machine.
library(future)
# A simple future: computation happens asynchronously
f <- future({
Sys.sleep(0.5) # simulate slow work
42
})
cat('Future created, doing other work...\n')
# Retrieve the result (blocks until done)
result <- value(f)
cat('Result:', result, '\n')plan() : choisir un moteur d’exécution
plan() définit la stratégie d’exécution de tous les futures suivants. Les stratégies les plus courantes sont sequential (par défaut, avec un seul thread), multisession (plusieurs sessions R, fonctionne partout) et multicore (création de processus par duplication, uniquement sous Unix/macOS).
library(future)
# Default: sequential (no parallelism)
plan(sequential)
cat('Strategy:', class(plan())[1], '\n')
# Parallel with separate R sessions (works on Windows too)
plan(multisession, workers = 4)
cat('Strategy:', class(plan())[1], '\n')
# Forking (Unix/macOS only, lower overhead)
if (.Platform$OS.type != 'windows') {
plan(multicore, workers = 4)
cat('Strategy:', class(plan())[1], '\n')
}
# Reset to sequential
plan(sequential)value() : attendre les résultats
value(f) bloque le processus actuel jusqu’à la fin du calcul du future, puis renvoie le résultat. Si le future a généré une erreur, value() la relance dans la session appelante.
library(future)
plan(multisession, workers = 2)
# Launch two slow tasks concurrently
f1 <- future({ Sys.sleep(0.3); sum(1:1000) })
f2 <- future({ Sys.sleep(0.3); prod(1:10) })
# Both run in parallel; total time ~ 0.3s not 0.6s
start <- proc.time()[['elapsed']]
v1 <- value(f1)
v2 <- value(f2)
elapsed <- proc.time()[['elapsed']] - start
cat('v1:', v1, ' v2:', v2, '\n')
cat('Elapsed:', round(elapsed, 2), 's\n')
plan(sequential)L’opérateur %<-%
L’opérateur %<-% est un raccourci syntaxique pour future() + value() différé. Il ressemble à une affectation ordinaire, mais le membre de droite s’exécute de manière asynchrone. La valeur est récupérée lors du premier accès à la variable.
library(future)
plan(multisession, workers = 2)
# %<-% starts the computation immediately in the background
x %<-% {
Sys.sleep(0.3)
rnorm(5, mean = 10)
}
y %<-% {
Sys.sleep(0.3)
runif(5, min = 1, max = 5)
}
cat('Both running in background...\n')
# Accessing x or y here blocks until ready
cat('x:', round(x, 2), '\n')
cat('y:', round(y, 2), '\n')
plan(sequential)Détection automatique des variables globales
L’une des fonctionnalités les plus puissantes de future est la détection des variables globales : le package trouve automatiquement les variables auxquelles votre code future fait référence dans l’environnement appelant et les envoie au processus de travail ; aucun clusterExport() manuel n’est nécessaire.
library(future)
plan(multisession, workers = 2)
# These globals are auto-detected and sent to the worker
threshold <- 50
multiplier <- 3
f <- future({
x <- threshold * multiplier # uses both globals
x + 1
})
cat('Result:', value(f), '\n') # 151
# Inspect which globals were identified
future_obj <- future({
threshold + multiplier
}, lazy = TRUE)
cat('Globals found:', paste(names(future::getGlobalsAndPackages(future_obj)$globals), collapse = ', '), '\n')
plan(sequential)future_options : régler le comportement
Les future.options (accessibles via les arguments de options() ou de future::plan()) contrôlent les paramètres globaux : la mémoire maximale autorisée par future, la stratégie de détection des variables globales et le comportement en cas de délai d’attente.
library(future)
# Cap memory per future at 500 MB
options(future.globals.maxSize = 500 * 1024^2) # bytes
# Disable automatic global detection (manual control)
options(future.globals.onReference = 'error')
# Inspect current settings
cat('Max globals size (MB):',
getOption('future.globals.maxSize') / 1024^2, '\n')
# Restore defaults
options(future.globals.maxSize = 500 * 1024^2)
options(future.globals.onReference = NULL)
plan(multisession, workers = 2)
# Large object: you'd get an error if it exceeds the cap
big_vec <- 1:1e5 # small enough
f <- future(sum(big_vec))
cat('Sum:', value(f), '\n')
plan(sequential)Futures imbriqués
Les futures peuvent être imbriqués : un future peut lui-même créer des futures internes. Par défaut, les futures internes s’exécutent séquentiellement, sauf si vous définissez un plan imbriqué avec plan(list(...)). Cette possibilité est utile pour le parallélisme à deux niveaux.
library(future)
# Two-level parallelism: outer uses multisession, inner sequential
plan(list(multisession, sequential))
outer_futures <- lapply(1:3, function(i) {
future({
# Each outer worker runs its own sequential inner work
inner <- lapply(1:4, function(j) i * j)
unlist(inner)
})
})
results <- lapply(outer_futures, value)
for (i in seq_along(results)) {
cat('Outer', i, ':', results[[i]], '\n')
}
plan(sequential)Gestion des erreurs avec les futures
Lorsqu’un calcul future génère une erreur, value() la relance. Entourez value() de tryCatch() pour gérer les erreurs de chaque future sans interrompre toute votre chaîne de traitement.
library(future)
plan(multisession, workers = 2)
# This future will error
bad_future <- future(log(-1, base = 'oops')) # invalid arg
good_future <- future(sqrt(144))
# Handle errors gracefully
bad_result <- tryCatch(
value(bad_future),
error = function(e) {
cat('Caught error:', conditionMessage(e), '\n')
NA
}
)
good_result <- value(good_future)
cat('bad_result:', bad_result, '\n')
cat('good_result:', good_result, '\n')
plan(sequential)Vérifier l’état d’un future
resolved(f) renvoie TRUE si un future est terminé, sans bloquer l’exécution. Vous pouvez ainsi vérifier régulièrement l’achèvement et effectuer un travail utile pendant l’attente, en créant une boucle de vérification non bloquante.
library(future)
plan(multisession, workers = 2)
f <- future({
Sys.sleep(0.5)
'done'
})
# Poll without blocking
counter <- 0
while (!resolved(f)) {
counter <- counter + 1
Sys.sleep(0.1)
cat('Polling... (', counter, ')\n')
}
cat('Future resolved! Result:', value(f), '\n')
cat('Polled', counter, 'times\n')
plan(sequential)Combiner future et lapply
Combinez lapply() avec future() pour répartir N tâches, puis lapply() avec value() pour recueillir les résultats. Ce modèle vous donne un contrôle explicite sur le moment où chaque future démarre.
library(future)
plan(multisession, workers = 4)
# Fan out: create all futures
params <- list(
list(n = 1000, mean = 0),
list(n = 1000, mean = 5),
list(n = 1000, mean = 10),
list(n = 1000, mean = -3)
)
futures <- lapply(params, function(p) {
future({
x <- rnorm(p$n, mean = p$mean)
list(mean = mean(x), sd = sd(x))
})
})
# Fan in: collect results
results <- lapply(futures, value)
for (i in seq_along(results)) {
cat('Param mean', params[[i]]$mean,
'-> observed mean:', round(results[[i]]$mean, 3), '\n')
}
plan(sequential)Cas concret : évaluation des partitions de validation croisée
La validation croisée est un problème naturellement parallélisable : chaque partition est indépendante. Avec les futures, vous pouvez évaluer les K partitions simultanément et réduire considérablement le temps réel nécessaire aux modèles coûteux.
library(future)
plan(multisession, workers = 4)
set.seed(42)
data <- data.frame(x = rnorm(200), y = rnorm(200))
fold_ids <- sample(rep(1:4, 50))
# Launch all folds in parallel
fold_futures <- lapply(1:4, function(k) {
future({
train <- data[fold_ids != k, ]
test <- data[fold_ids == k, ]
fit <- lm(y ~ x, data = train)
preds <- predict(fit, newdata = test)
rmse <- sqrt(mean((test$y - preds)^2))
rmse
})
})
rmses <- unlist(lapply(fold_futures, value))
cat('Fold RMSEs:', round(rmses, 4), '\n')
cat('Mean RMSE:', round(mean(rmses), 4), '\n')
plan(sequential)Vérification rapide
Vous souhaitez exécuter du code parallèle qui fonctionne sur Windows et macOS. Quelle stratégie plan() devez-vous choisir ?
Récapitulatif : environnement future
À retenir :
future({expr})exécute une expression de manière asynchrone ;value(f)récupère le résultat%<-%est un raccourci syntaxique : une affectation avec évaluation différée du futureplan(multisession)convient à plusieurs systèmes ;plan(multicore)utilise la création de processus par duplication sous Unix/macOS- Les variables globales sont détectées automatiquement et envoyées aux processus de travail ; aucun
clusterExport()n’est nécessaire resolved(f)vérifie l’achèvement sans bloquer- Entourez
value()detryCatch()pour des chaînes de traitement résistantes aux erreurs - Appelez toujours
plan(sequential)ouplan()pour réinitialiser la stratégie une fois le travail terminé
library(future)
plan(multisession, workers = 2)
# Concise pattern: fan-out then fan-in
task <- function(i) future({ i^2 + i })
results <- lapply(1:6, task)
cat(unlist(lapply(results, value)), '\n') # 2 6 12 20 30 42
plan(sequential)Questions Fréquemment Posées
La leçon « Le cadriciel future » est-elle gratuite ?
Oui — le texte complet de « Le cadriciel future » 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 « Le cadriciel future » ?
Utilisez plan(multisession) et future() pour effectuer un traitement parallèle asynchrone et portable. 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 2 sur 4.
Combien de temps prend la leçon « Le cadriciel future » ?
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