2015-07-26 24 views
17

Próbuję dowiedzieć się, jak wdrożyć funkcję dplyr::do równolegle. Po przeczytaniu niektórych dokumentów wydaje się, że dplyr :: init_cluster() powinien wystarczyć, aby polecenie do() działało równolegle. Niestety, to nie wydaje się być przypadek, kiedy to sprawdzić:Jak wykonać równoległe wywoływania do() z 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() 

Daje to wyjście:

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

Spodziewam się, że będzie 3 czy wywołanie zrobić została podzielona pomiędzy dwa rdzenie . Mogę to również potwierdzić, dodając wydruk do funkcji do(), która drukuje w głównym terminalu R. Czego tu mi brakuje?

Używam dplyr 0.4.2 R 3.2.1

+0

Odkryłam, że dla kodu naprawdę krytycznym, najlepszym sposobem, przynajmniej dla moich przypadków użycia, jest uzyskanie brudne ręce z Rcpp i OpenMP. Wykracza to głównie poza moje umiejętności informatyczne, ale wydaje się, że istnieje wiele subtelnych interakcji w pamięci podręcznej, a czasem także dziwek procesora lub kompilatora, które trzeba dokładnie profilować i porównywać. Zauważyłem również, że struktura danych często przyniosła największą różnicę i może znacznie pomóc w równoległym tworzeniu. Powodzenia! –

Odpowiedz

22

Zgodnie mentionned przez @Maciej, można spróbować multidplyr:

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

Zastosowanie partition() podzielić swój zestaw danych w poprzek wielokrotność rdzeni:

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

Będziesz zainicjować 3 rdzenie klaster (po jednym na każdy a)

# Initialising 3 core cluster. 

Wtedy po prostu wykonywać swoją do() połączenia:

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

Co daje:

#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

Dzięki! Przejrzałam odpowiedź @ Macieja i to świetnie, że w końcu to się stało. Często wykonuję bardziej skomplikowane zadania niż te, które są dostępne w podsumowaniu i bez równoległości nie mogłem znaleźć dplyra, który jest tak przydatny, jak twierdzą. –

+0

@MaxGordon Cieszę się, że pomogło! –

+0

W jaki sposób wysyłasz zdefiniowaną przez użytkownika funkcję, która ma zostać wykonana za pomocą 'do()' do każdego węzła? Otrzymuję komunikat "funkcja nie została znaleziona" – Dominik

Powiązane problemy