Introducción
El paquete furrr amplía la funcionalidad de purrr al permitir el procesamiento paralelo mediante futuros. Esto significa que puede transformar fácilmente sus flujos de trabajo secuenciales, tidyverse en flujos paralelizados, acelerando sus cálculos sin sacrificar la legibilidad del código. En este tutorial, aprenderá a configurar furrr, configurar planes futuros para la ejecución en paralelo y aplicar funciones como future_map()
para procesar datos de forma concurrente.
Instalar y cargar furrr
En primer lugar, asegúrese de que tiene furrr instalado. Puedes instalarlo desde CRAN si es necesario:
#| label: install-furrr
install.packages("furrr")
# Cargar el paquete furrr
library(furrr)
Configuración de un plan futuro
Antes de utilizar las funciones furrr
, es necesario establecer un plan future
que determine cómo se distribuyen las tareas. Por ejemplo, para ejecutar tareas en paralelo utilizando múltiples sesiones:
#| label: set-future-plan
library(future)
# Establecer el plan para usar multisesión
1plan(multisession, workers = availableCores() - 1)
- 1
- Configure el plan para utilizar varias sesiones, con el número de trabajadores igual a los núcleos disponibles menos uno. Esto es adecuado para la mayoría de las máquinas locales.
Usar las funciones de furrr
La función central de furrr es future_map()
, que funciona de forma similar a purrr::map()
pero ejecuta las operaciones en paralelo.
Ejemplo: Asignación paralela
#| label: future-map-example
# Crear un vector simple
<- 1:10
numbers
# Calcular el cuadrado de cada número en paralelo
<- future_map(numbers, ~ .x^2)
squared_numbers print(squared_numbers)
Ejemplo: Devolución de tipos específicos con future_map_dbl()
Si espera una salida numérica, puede utilizar future_map_dbl()
para devolver un vector doble:
#| label: future-map-dbl-example
# Calcule raíces cuadradas en paralelo, garantizando una salida de vector numérico
<- future_map_dbl(numbers, ~ sqrt(.x))
sqrt_values print(sqrt_values)
Comparación de los flujos de trabajo purrr y furrr
Para ilustrar las ventajas de rendimiento del procesamiento paralelo, comparemos un flujo de trabajo purrr estándar con su versión paralelizada utilizando furrr. En los ejemplos siguientes, simularemos una tarea de cálculo intensivo utilizando Sys.sleep()
.
Flujo de trabajo estándar de purrr
#| label: purrr-workflow
library(purrr)
# Defina una función computacionalmente intensiva
# Simular una tarea que consume tiempo
<- function(x) {
heavy_computation Sys.sleep(6)
^2
x
}
# Ejecución secuencial con purrr::map
<- system.time({
seq_time <- map(1:10, heavy_computation)
seq_result
})print("Sequential purrr execution time:")
print(seq_time)
Resultado: Tiempo de ejecución secuencial de furrr
user system elapsed
0.188 0.000 60.226
Flujo de trabajo paralelo con furrr
#| label: furrr-workflow
library(furrr)
# Establecer el plan para usar multisesión
plan(multisession, workers = availableCores() - 1)
# Ejecución paralela usando furrr::future_map
<- system.time({
par_time <- future_map(1:10, heavy_computation)
par_result
})print("Parallel furrr execution time:")
print(par_time)
Tiempo de ejecución Tiempo de ejecución paralela de purrr
user system elapsed
4.973 0.083 27.949
Al comparar el rendimiento, es importante centrarse en el tiempo transcurrido (reloj de pared) en lugar de sólo en el tiempo de CPU del usuario.
En nuestras pruebas, el flujo de trabajo secuencial con purrr
tardó unos 60,226 segundos, mientras que la versión paralelizada con furrr
se completó en sólo 27,949 segundos.
Aunque el enfoque furrr mostró un mayor tiempo de CPU del usuario debido al uso concurrente de múltiples núcleos, la clave es que el tiempo total de espera experimentado por el usuario se redujo casi a la mitad.
Esto demuestra claramente el beneficio del procesamiento paralelo para reducir el tiempo total de ejecución de tareas que consumen muchos recursos.
Buenas Prácticas
Establecer un plan futuro apropiado:
Elija un planfuture
que se ajuste a las capacidades de su sistema (por ejemplo,multisession
para el procesamiento paralelo local).Monitorizar el uso de recursos:
El procesamiento en paralelo puede consumir muchos recursos. Ajusta el número de trabajadores usandoavailableCores()
para asegurarte de que tu sistema sigue respondiendo.Pruebe primero secuencialmente:
Antes de paralelizar su código con furrr, pruébelo secuencialmente usando purrr para asegurar su corrección. A continuación, cambie a furrr para mejorar el rendimiento.Gestión de errores:
Considere el uso de envolturas de gestión de errores (por ejemplo,safely()
opossibly()
) de purrr junto confurrr
para gestionar posibles errores en tareas paralelas.
Conclusión
furrr
ofrece una forma sencilla de actualizar sus flujos de trabajo tidyverse
con capacidades de procesamiento paralelo. Estableciendo un plan de futuro y utilizando funciones como future_map()
y future_map_dbl()
, puedes mejorar significativamente el rendimiento de tu código R sin sacrificar la legibilidad. La comparación entre los flujos de trabajo purrr
y furrr
ilustra el aumento potencial de velocidad que se puede conseguir mediante la paralelización.
Lecturas adicionales
Disfrute codificando y aprovechando furrr para acelerar sus flujos de trabajo en R!
Explorar más artículos
Aquí hay más artículos de la misma categoría para ayudarte a profundizar en el tema.
Reutilización
Cómo citar
@online{kassambara2024,
author = {Kassambara, Alboukadel},
title = {Procesamiento paralelo en R con furrr},
date = {2024-02-10},
url = {https://www.datanovia.com/es/learn/programming/r/advanced/furrr-for-parallel-processing.html},
langid = {es}
}