Introdução
O pacote furrr amplia a funcionalidade do purrr, permitindo o processamento paralelo usando futuros. Isso significa que você pode transformar facilmente seus fluxos de trabalho sequenciais e compatíveis com tidyverse em fluxos paralelizados, acelerando seus cálculos sem sacrificar a legibilidade do código. Neste tutorial, você aprenderá como configurar o furrr, definir planos futuros para execução paralela e aplicar funções como future_map()
para processar dados simultaneamente.
Instalando e carregando furrr
Primeiro, certifique-se de que você tem furrr instalado. Você pode instalá-lo a partir do CRAN, se necessário:
#| label: install-furrr
install.packages("furrr")
# Carregue o pacote furrr
library(furrr)
Definindo um plano futuro
Antes de usar as funções furrr
, você precisa definir um plano future
que determine como as tarefas serão distribuídas. Por exemplo, para executar tarefas em paralelo usando várias sessões:
#| label: set-future-plan
library(future)
# Definir o plano para usar multissessão
1plan(multisession, workers = availableCores() - 1)
- 1
- Defina o plano para usar várias sessões, com o número de trabalhadores igual aos núcleos disponíveis menos um. Isso é adequado para a maioria das máquinas locais.
Usando funções furrr
A função principal fornecida pelo furrr é future_map()
, que funciona de maneira semelhante a purrr::map()
, mas executa operações em paralelo.
Exemplo: mapeamento paralelo
#| label: future-map-example
# Crie um vetor simples
<- 1:10
numbers
# Calcule o quadrado de cada número em paralelo
<- future_map(numbers, ~ .x^2)
squared_numbers print(squared_numbers)
Exemplo: retornando tipos específicos com future_map_dbl()
Se você espera uma saída numérica, pode usar future_map_dbl()
para retornar um vetor duplo:
#| label: future-map-dbl-example
# Calcule raízes quadradas em paralelo, garantindo uma saída de vetor numérico
<- future_map_dbl(numbers, ~ sqrt(.x))
sqrt_values print(sqrt_values)
Comparando os fluxos de trabalho purrr e furrr
Para ilustrar os benefícios de desempenho do processamento paralelo, vamos comparar um fluxo de trabalho purrr padrão com sua versão paralelizada usando furrr. Nos exemplos abaixo, simularemos uma tarefa computacionalmente intensiva usando Sys.sleep()
.
Fluxo de trabalho padrão do purrr
#| label: purrr-workflow
library(purrr)
# Defina uma função computacionalmente intensiva
# Simule uma tarefa demorada
<- function(x) {
heavy_computation Sys.sleep(6)
^2
x
}
# Execução sequencial usando purrr::map
<- system.time({
seq_time <- map(1:10, heavy_computation)
seq_result
})print("Sequential purrr execution time:")
print(seq_time)
Saída: tempo de execução sequencial do purrr
user system elapsed
0.188 0.000 60.226
Fluxo de trabalho paralelizado com furrr
#| label: furrr-workflow
library(furrr)
# Definir o plano para usar multissessão
plan(multisession, workers = availableCores() - 1)
# Execução 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)
Saída: tempo de execução paralela do furrr
user system elapsed
4.973 0.083 27.949
Ao comparar o desempenho, é importante se concentrar no tempo decorrido (tempo real) em vez de apenas no tempo de CPU do usuário.
Em nossos benchmarks, o fluxo de trabalho sequencial usando purrr
levou cerca de 60,226 segundos de tempo decorrido, enquanto a versão paralelizada com furrr
foi concluída em apenas 27,949 segundos.
Embora a abordagem furrr tenha apresentado maior tempo de CPU do usuário devido ao uso simultâneo de vários núcleos, a principal conclusão é que o tempo de espera geral experimentado pelo usuário foi quase reduzido pela metade.
Isso demonstra claramente a vantagem do processamento paralelo para reduzir o tempo total de execução de tarefas que consomem muitos recursos.
Práticas recomendadas
Defina um plano futuro adequado:
Escolha um planofuture
que corresponda aos recursos do seu sistema (por exemplo,multisession
para processamento paralelo local).Monitore o uso de recursos:
O processamento paralelo pode consumir recursos significativos. Ajuste o número de trabalhadores usandoavailableCores()
para garantir que seu sistema permaneça responsivo.Teste sequencialmente primeiro:
Antes de paralelizar seu código com furrr, teste-o sequencialmente usando purrr para garantir a correção. Em seguida, mude para furrr para obter melhorias de desempenho.Tratamento de erros:
Considere usar wrappers de tratamento de erros (por exemplo,safely()
oupossibly()
) do purrr em conjunto comfurrr
para gerenciar erros potenciais em tarefas paralelas.
Conclusão
furrr
oferece uma maneira perfeita de atualizar seus fluxos de trabalho tidyverse
com recursos de processamento paralelo. Ao definir um plano futuro e usar funções como future_map()
e future_map_dbl()
, você pode melhorar significativamente o desempenho do seu código R sem sacrificar a legibilidade. A comparação entre os fluxos de trabalho purrr
e furrr
ilustra os ganhos de velocidade potenciais que podem ser obtidos por meio da paralelização.
Leitura adicional
Boa programação e aproveite o furrr para acelerar seus fluxos de trabalho R!
Explore mais artigos
Aqui estão mais artigos da mesma categoria para ajudá-lo a se aprofundar no tópico.
Reuso
Citação
@online{kassambara2024,
author = {Kassambara, Alboukadel},
title = {Processamento paralelo em R com furrr},
date = {2024-02-10},
url = {https://www.datanovia.com/pt/learn/programming/r/advanced/furrr-for-parallel-processing.html},
langid = {pt}
}