2013-07-07 2 views
7

일반적인 배열을 병렬로 채우기 위해 R에서 두 개의 foreach 루프를 사용하려고합니다. 내가 뭘하려고 오전의 매우 단순화 된 버전은 다음과 같습니다일반적인 배열을 업데이트하기 위해 R에 중첩 된 foreach 루프

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. 

    } 
} 

내가 병렬 매트릭스 x를 업데이트하고 같은 출력 모양이 코드 싶습니다 그러나

> 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 

을, 난 못해 배열을 업데이트하는 방법을 알아내는 것 같습니다. 다른 곳에서는 x <-을 넣으려고했으나 좋아하지 않습니다. 나는 이것이 매우 쉬운 문제 일 것이라고 생각하지만, 나의 모든 수색은 아직 나를 거기에 인도하지 못했다. 감사.

+1

안녕하세요, 일반적인 팁 : 특정 패키지를 사용하는 경우 샘플 코드에이를 나타내면 도움이됩니다. (반영하도록 코드를 편집했습니다.) –

+0

Thanks @RicardoSaporta 예를 작게 만들 때 깜박 했으니 – joshdr83

답변

11

foreach 루프는 반환 값에 대해 lapply과 같이 사용됩니다. 이 방법으로 그들은 그들의 부작용에 사용되는 for 루프와 매우 다릅니다. %:% :

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

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

은 또한 중첩 연산자를 사용할 수있다 : 적절한 .combine 함수를 사용하여, 내부 foreach 루프 외측 foreach 루프에 의해 행렬로 행 방향으로 결합되는 벡터를 반환 할

set.seed은 아마도 로컬 컴퓨터에서 수행되기 때문에 원하는 작업을 수행하지 못하고 임의의 숫자는 다른 컴퓨터에서 다른 R 세션에서 생성됩니다.

+0

이 'set.seed'에 대해 인식하지 못했습니다. - 그 점을 지적 해 주셔서 감사합니다. –

+0

씨 뿌리기에 대한 좋은 점! – cryo111

+0

신난다, 고마워! – joshdr83

2

Steve의 대답에 뭔가를 추가하기 만하면됩니다. 중요한 점은 병렬 백엔드가 여러 Rscript.exe 프로세스를 시작한다는 것입니다 (작업 관리자에서 볼 수있는 것처럼). foreach, 즉 귀하의 경우 x에 사용되는 특정 개체는 각각 이며 이러한 각 프로세스에 할당 된 메모리에이 복사됩니다. foreach 패키지에서 복사가 어떻게 처리되는지 모르지만 plyr 패키지의 *ply 기능을 사용하면 복사해야 할 개체를 명시 적으로 명시해야합니다. 서로 다른 프로세스가 메모리를 공유하지 않습니다.

하나는 매트릭스 x 실제로의 x 메모리 위치를 개체를 인쇄 할 수 .Internal(inspect(x))를 사용하여 복사되고 있음을 입증 할 수 있습니다 (I는 ... 공유 메모리를 사용할 수있는 다른 R 패키지를 인식하지 않다).

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) 

매트릭스 y 당신이 두 개의 서로 다른 메모리 주소를 찾을 수 있어야

 [,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,..." 
... 

을 읽습니다.