El framework future
Use plan(multisession) y future() para ejecutar paralelismo asíncrono y portable.
El framework future es una lección gratuita de R Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de R Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de R Academy incluye 4 lecciones en total.
¿Qué es el paquete future?
El paquete future proporciona una API unificada y de alto nivel para la programación asíncrona y paralela en R. Un future es un marcador de posición para un valor que estará disponible más adelante, posiblemente calculado en otro núcleo o equipo.
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(): Selección de un backend
plan() establece la estrategia de ejecución para todos los futures posteriores. Las estrategias más comunes son sequential (predeterminada, de un solo subproceso), multisession (varias sesiones de R, funciona en cualquier sistema) y multicore (bifurcación de procesos, solo 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(): Espera de resultados
value(f) bloquea el proceso actual hasta que termina el cálculo del future y, después, devuelve el resultado. Si el future produjo un error, value() vuelve a lanzarlo en la sesión que realizó la llamada.
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)El operador %<-%
El operador %<-% es una abreviatura sintáctica de future() + value() diferido. Tiene el aspecto de una asignación normal, pero el lado derecho se ejecuta de forma asíncrona. El valor se recupera la primera vez que se accede a 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)Detección automática de globales
Una de las funciones más potentes de future es la detección de variables globales: encuentra automáticamente las variables a las que hace referencia el código del future en el entorno de llamada y las envía al worker; no se necesita clusterExport() manualmente.
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: Ajuste del comportamiento
Las opciones de future.options (a las que se accede mediante los argumentos de options() o future::plan()) controlan la configuración global: la memoria máxima permitida por future, la estrategia de detección de globales y el comportamiento de los tiempos de espera.
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 anidados
Los futures pueden anidarse: un future puede crear a su vez futures internos. De forma predeterminada, los futures internos se ejecutan secuencialmente, a menos que establezca un plan anidado con plan(list(...)). Esto resulta útil para el paralelismo de dos niveles.
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)Gestión de errores con futures
Cuando un cálculo de un future produce un error, value() vuelve a lanzarlo. Envuelva value() en tryCatch() para gestionar los errores de futures individuales sin detener toda la canalización.
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)Comprobación del estado de un future
resolved(f) devuelve TRUE si un future ha terminado, sin bloquear la ejecución. Esto permite consultar si ha finalizado y realizar trabajo útil mientras espera, creando un bucle de consulta no bloqueante.
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)Combinación de future con lapply
Combine lapply() con future() para distribuir N tareas, y lapply() con value() para recopilar los resultados. Este patrón le proporciona un control explícito sobre cuándo comienza cada future.
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)Caso de uso real: evaluación de particiones de validación cruzada
La validación cruzada es un problema fácilmente paralelizable: cada partición es independiente. Con futures puede evaluar las K particiones simultáneamente, reduciendo considerablemente el tiempo de ejecución de modelos costosos.
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)Comprobación rápida
Desea ejecutar código paralelo que funcione tanto en Windows como en macOS. ¿Qué estrategia de plan() debería elegir?
Resumen: framework future
Ideas clave:
future({expr})ejecuta una expresión de forma asíncrona;value(f)recupera el resultado%<-%es una abreviatura sintáctica: una asignación con evaluación diferida del future- Use
plan(multisession)para la compatibilidad multiplataforma yplan(multicore)para la bifurcación en Unix/macOS - Las variables globales se detectan automáticamente y se envían a los workers; no se necesita
clusterExport() resolved(f)comprueba si la ejecución terminó sin bloquearla- Envuelva
value()entryCatch()para crear canalizaciones resistentes a errores - Llame siempre a
plan(sequential)oplan()para restablecer la configuración al terminar
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)Aprende R con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 43
- Lecciones
- 159
Preguntas frecuentes
¿La lección «El framework future» es gratis?
Sí — el texto completo de «El framework future» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de R Academy, actualiza a CoddyKit PRO. El curso de R Academy incluye 4 lecciones en total.
¿Qué aprenderé en «El framework future»?
Use plan(multisession) y future() para ejecutar paralelismo asíncrono y portable. Practicas R Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar R Academy?
No se requiere experiencia previa. R Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «El framework future»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de R Academy?
Sí. Cada lección de R Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Paquete parallel y detectCores()
- El framework future
- furrr: operaciones paralelas de purrr
- Depuración y equilibrio de carga del código paralelo