2013-07-07 14 views
7

Próbuję użyć kilku pętli foreach w R, aby wypełnić wspólną tablicę równolegle. Bardzo uproszczona wersja tego, co próbuję zrobić, to:zagnieżdżone pętle foreach w R, aby zaktualizować wspólną tablicę

library(foreach) 
set.seed(123) 
x <- matrix(NA, nrow = 8, ncol = 2) 

foreach(i=1:8) %dopar% { 
    foreach(j=1:2) %do% { 

     l <- runif(1, i, 100) 
     x[i,j] <- i + j + l  #This is much more complicated in my real code. 

    } 
} 

Chciałbym kod, aby zaktualizować matrycę x równolegle i mają wygląd wyjścia jak:

> x 
     [,1]  [,2] 
[1,] 31.47017 82.04221 
[2,] 45.07974 92.53571 
[3,] 98.22533 12.41898 
[4,] 59.69813 95.67223 
[5,] 63.38633 55.37840 
[6,] 102.94233 56.61341 
[7,] 78.01407 69.25491 
[8,] 26.46907 100.78390 

Jednak nie mogę wydają się wymyślać, jak uzyskać aktualizację tablicy. Próbowałem umieścić w innym miejscu x <-, ale wydaje się, że to nie podoba. Myślę, że to bardzo łatwa rzecz do naprawienia, ale wszystkie moje poszukiwania jeszcze mnie tam nie doprowadziły. Dzięki.

+1

Cześć, tylko ogólna wskazówka: jeśli korzystasz z określonego pakietu, warto to zaznaczyć w przykładowym kodzie. (Poprawiłem twój kod) –

+0

Dzięki @RicardoSaporta Zapomniałem tego zrobić, gdy robiłem mały przykład: – joshdr83

Odpowiedz

11

foreach pętle są używane dla ich wartości zwracanej, np. lapply. W ten sposób są one bardzo różne od pętli for, które są wykorzystywane do ich efektów ubocznych. Dzięki zastosowaniu odpowiednich .combine funkcji wewnętrzna foreach pętla może powrócić wektory, które są połączone w rzędach w matrycy przez zewnętrzną foreach pętli:

x <- foreach(i=1:8, .combine='rbind') %dopar% { 
    foreach(j=1:2, .combine='c') %do% { 
    l <- runif(1, i, 100) 
    i + j + l 
    } 
} 

można również wykorzystać do zagnieżdżania operatora: %:%:

x <- foreach(i=1:8, .combine='rbind') %:% 
    foreach(j=1:2, .combine='c') %dopar% { 
    l <- runif(1, i, 100) 
    i + j + l 
    } 

Zauważ, że prawdopodobnie set.seed nie zrobi tego, co chcesz, ponieważ jest wykonywane na komputerze lokalnym, podczas gdy liczby losowe są generowane w różnych sesjach R, prawdopodobnie na różnych komputerach.

+0

nie zdawałem sobie z tego sprawy z powodu 'set.seed' - dziękuję za wskazanie tego na –

+0

Dobra rada o wysiewie! – cryo111

+0

Niesamowite, dzięki chłopaki! – joshdr83

2

Wystarczy dodać coś do odpowiedzi Steve'a: Myślę, że kluczowe jest to, że równoległy backend uruchamia wiele procesów Rscript.exe (jak widać w menedżerze zadań). Pewne obiekty używane w ramach foreach, tj. W twoim przypadku x, są następnie skopiowane do pamięci przydzielonej dla każdego z tych procesów. Nie mam pewności, jak kopiowanie jest obsługiwane w pakiecie foreach, ale z funkcjami *ply pakietu plyr należy jawnie określić obiekty, które powinny zostać skopiowane. Poszczególne procesy nie udostępniają swojej pamięci. (Nie jestem świadomy innych pakietów R, które mogą korzystać z pamięci współdzielonej ...)

Można wykazać, że matryca x faktycznie kopiowane za pomocą .Internal(inspect(x)) wydrukować obiekt x „s lokalizację pamięci.

library(foreach) 
library(doParallel) 

x <- matrix(1:16, nrow = 8, ncol = 2) 
#print memory location of x 
capture.output(.Internal(inspect(x)))[1] 

#create parallel backend; in our case two Rscript.exe processes 
workers=makeCluster(2) 
registerDoParallel(workers) 

y<- foreach(i=1:8, .combine='rbind') %dopar% { 
    #return memory location of x 
    capture.output(.Internal(inspect(x)))[1] 
} 

#print matrix y 
#there should be two different memory locations - 
#according to the two Rscript.exe processes started above 
y 

#close parallel backend 
stopCluster(workers) 

Matryca y czyta

 [,1]                   
result.1 "@0x0000000003dab910 13 INTSXP g0c5 [NAM(1),ATT] (len=16, tl=0) 1,2,3,4,5,..." 
result.2 "@0x0000000003dab9b0 13 INTSXP g0c5 [NAM(1),ATT] (len=16, tl=0) 1,2,3,4,5,..." 
result.3 "@0x0000000003dab910 13 INTSXP g0c5 [NAM(2),ATT] (len=16, tl=0) 1,2,3,4,5,..." 
result.4 "@0x0000000003dab910 13 INTSXP g0c5 [NAM(2),ATT] (len=16, tl=0) 1,2,3,4,5,..." 
... 

Powinieneś znaleźć tam dwa różne adresy pamięci.

Powiązane problemy