2015-07-26 26 views
17

Sto cercando di capire come distribuire la funzione dplyr::do in parallelo. Dopo aver letto alcuni documenti sembra che dplyr :: init_cluster() dovrebbe essere sufficiente per dire a do() di funzionare in parallelo. Purtroppo questo non sembra essere il caso quando prova questo:Come parallelizzare le chiamate do() con dplyr

library(dplyr) 
test <- data_frame(a=1:3, b=letters[c(1:2, 1)]) 

init_cluster() 
system.time({ 
    test %>% 
    group_by(b) %>% 
    do({ 
     Sys.sleep(3) 
     data_frame(c = rep(max(.$a), times = max(.$a))) 
    }) 
}) 
stop_cluster() 

dà questa uscita:

Initialising 2 core cluster. 
|==========================================================================|100% ~0 s remaining 
    user system elapsed 
    0.03 0.00 6.03 

mi sarei aspettato di essere 3 se la chiamata fare è stato diviso tra i due core . Posso anche confermarlo aggiungendo una stampa al do() che stampa nel terminale R principale. Cosa mi manca qui?

sto usando dplyr 0.4.2 con R 3.2.1

+0

ho trovato che per il codice davvero critica, il modo migliore, almeno per i miei casi d'uso, è quello di ottenere le tue mani sporche con Rcpp e OpenMP. È in gran parte al di là delle mie capacità informatiche, ma sembra che ci siano così tante interazioni cache e talvolta qualche stranezza nel processore o nel compilatore, che è necessario solo un profilo e un benchmark con attenzione. Ho anche trovato che strutturare bene i dati spesso ha fatto la differenza più grande e potrebbe aiutare in modo significativo la parallelizzazione. In bocca al lupo! –

risposta

22

Secondo menzionati da @Maciej, si potrebbe provare multidplyr:

## Install from github 
devtools::install_github("hadley/multidplyr") 

Usa partition() per dividere il set di dati attraverso multipli core:

library(dplyr) 
library(multidplyr) 
test <- data_frame(a=1:3, b=letters[c(1:2, 1)]) 
test1 <- partition(test, a) 

sarete inizializzare una 3 nuclei cluster (uno per ogni a)

# Initialising 3 core cluster. 

Poi basta eseguire la do() chiamata:

test1 %>% 
    do({ 
    dplyr::data_frame(c = rep(max(.$a)), times = max(.$a)) 
    }) 

che dà:

#Source: party_df [3 x 3] 
#Groups: a 
#Shards: 3 [1--1 rows] 
# 
#  a  c times 
# (int) (int) (int) 
#1  1  1  1 
#2  2  2  2 
#3  3  3  3 
+2

Grazie! Ho esaminato la risposta di @ Maciej ed è fantastico che questo sia finalmente arrivato. Faccio spesso compiti più complessi di quelli disponibili in sintesi e senza la parallelizzazione non potrei davvero trovare dplyr così utile come molti sostengono che sia. –

+0

@MaxGordon Sono contento che ci abbia aiutato! –

+0

Come si invia una funzione definita dall'utente che deve essere eseguita con 'do()' su ciascun nodo? Sto ottenendo "funzione non trovata" – Dominik

Problemi correlati