Introduction
Le paquet furrr étend les fonctionnalités de purrr en permettant le traitement parallèle à l’aide de futures. Cela signifie que vous pouvez facilement transformer vos flux de travail séquentiels, tidyverse conviviaux, en flux parallélisés, ce qui accélère vos calculs sans sacrifier la lisibilité du code. Dans ce tutoriel, vous apprendrez à mettre en place furrr, à configurer les plans futurs pour l’exécution parallèle et à appliquer des fonctions telles que future_map()
pour traiter les données de manière concurrente.
Installation et chargement de furrr
Assurez-vous d’abord que vous avez installé furrr. Vous pouvez l’installer à partir du CRAN si nécessaire:
#| label: install-furrr
install.packages("furrr")
# Charger le paquetage purrr
library(furrr)
Mise en place d’un plan futur
Avant d’utiliser les fonctions furrr
, vous devez définir un plan 585abb657c193e409cdd5cd8bcbd2d qui détermine la manière dont les tâches sont réparties. Par exemple, pour exécuter des tâches en parallèle en utilisant plusieurs sessions:
#| label: set-future-plan
library(future)
# Définir le plan d'utilisation de la multisession
1plan(multisession, workers = availableCores() - 1)
- 1
- Définissez le plan pour utiliser plusieurs sessions, avec un nombre de travailleurs égal au nombre de cœurs disponibles moins un. Cette méthode convient à la plupart des machines locales.
Utiliser les fonctions de furrr
La fonction principale fournie par furrr est future_map()
, qui fonctionne de manière similaire à purrr::map()
mais exécute les opérations en parallèle.
Exemple : Cartographie parallèle
#| label: future-map-example
# Créer un vecteur simple
<- 1:10
numbers
# Calculer le carré de chaque nombre en parallèle
<- future_map(numbers, ~ .x^2)
squared_numbers print(squared_numbers)
Exemple : Renvoi de types spécifiques avec future_map_dbl()
Si vous attendez un résultat numérique, vous pouvez utiliser future_map_dbl()
pour renvoyer un double vecteur:
#| label: future-map-dbl-example
# Calculer des racines carrées en parallèle, en garantissant une sortie numérique
<- future_map_dbl(numbers, ~ sqrt(.x))
sqrt_values print(sqrt_values)
Comparaison des flux de travail purrr et furrr
Pour illustrer les avantages du traitement parallèle en termes de performances, comparons un flux de travail purrr standard à sa version parallélisée à l’aide de furrr. Dans les exemples ci-dessous, nous allons simuler une tâche à forte intensité computationnelle en utilisant Sys.sleep()
.
Flux de travail standard de purrr
#| label: purrr-workflow
library(purrr)
# Définir une fonction à forte intensité de calcul
# Simuler une tâche qui prend du temps
<- function(x) {
heavy_computation Sys.sleep(6)
^2
x
}
# Exécution séquentielle à l'aide de purrr::map
<- system.time({
seq_time <- map(1:10, heavy_computation)
seq_result
})print("Sequential purrr execution time:")
print(seq_time)
Résultat : Temps d’exécution séquentiel de purrr
user system elapsed
0.188 0.000 60.226
Flux de travail parallélisé avec furrr
#| label: furrr-workflow
library(furrr)
# Définir le plan d'utilisation de la multisession
plan(multisession, workers = availableCores() - 1)
# Exécution parallèle à l'aide de furrr::future_map
<- system.time({
par_time <- future_map(1:10, heavy_computation)
par_result
})print("Parallel furrr execution time:")
print(par_time)
Sortie : Temps d’exécution de purrr en parallèle
user system elapsed
4.973 0.083 27.949
Lors de la comparaison des performances, il est important de se concentrer sur le temps écoulé (horloge murale) plutôt que sur le temps CPU de l’utilisateur.
Dans nos benchmarks, le flux de travail séquentiel utilisant purrr
a pris environ 60.226 secondes de temps écoulé, alors que la version parallélisée avec furrr
s’est achevée en seulement 27.949 secondes.
Bien que l’approche furrr ait montré un temps CPU plus élevé pour l’utilisateur en raison de l’utilisation simultanée de plusieurs cœurs, l’essentiel est que le temps d’attente global subi par l’utilisateur a été presque divisé par deux.
Cela démontre clairement l’avantage du traitement parallèle pour réduire le temps d’exécution total des tâches à forte intensité de ressources.
Bonnes pratiques
Définir un plan futur approprié:
Choisissez un plan 585abb657c193e409cdd5cd8bcbd2d qui correspond aux capacités de votre système (par exemple,multisession
pour le traitement parallèle local).Surveiller l’utilisation des ressources:
Le traitement parallèle peut consommer des ressources importantes. Ajustez le nombre de travailleurs en utilisantavailableCores()
pour vous assurer que votre système reste réactif.Tester d’abord séquentiellement:
Avant de paralléliser votre code avec furrr, testez-le séquentiellement avec purrr pour vous assurer qu’il est correct. Passez ensuite à furrr pour améliorer les performances.Gestion des erreurs:
Envisager d’utiliser des wrappers de gestion des erreurs (par exemple,safely()
oupossibly()
) de purrr en conjonction avecfurrr
pour gérer les erreurs potentielles dans les tâches parallèles.
Conclusion
furrr
offre un moyen fluide de mettre à niveau vos workflows tidyverse
avec des capacités de traitement parallèle. En établissant un plan futur et en utilisant des fonctions telles que future_map()
et future_map_dbl()
, vous pouvez améliorer de manière significative les performances de votre code R sans en sacrifier la lisibilité. La comparaison entre les flux de travail purrr
et furrr
illustre les gains de vitesse potentiels réalisables grâce à la parallélisation.
Plus d’informations
Bon codage, et profitez de l’utilisation de furrr pour accélérer vos flux de travail R!
Explorer d’autres articles
Voici d’autres articles de la même catégorie pour vous aider à approfondir le sujet.
Réutilisation
Citation
@online{kassambara2024,
author = {Kassambara, Alboukadel},
title = {Traitement parallèle en R avec furrr},
date = {2024-02-10},
url = {https://www.datanovia.com/fr/learn/programming/r/advanced/furrr-for-parallel-processing.html},
langid = {fr}
}