2013-07-07 8 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

ありがとう@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機能では、コピーするオブジェクトを明示的に指定する必要があります。 異なるプロセスは、そのメモリを共有しません。 (私は共有メモリを使用できる他のRパッケージについては気づきません...)xxのメモリ位置を印刷するためにを使って実際にコピーされていることを実証できます。

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

を読み込みます。

関連する問題