簡體   English   中英

R中的嵌套foreach循環更新公共數組

[英]nested foreach loops in R to update common array

我試圖在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 <-放在其他地方,但它似乎不喜歡它。 我認為這將是一個非常容易解決的問題,但我所有的搜索還沒有把我帶到那里。 謝謝。

foreach循環用於返回值,如lapply 這樣,他們來自非常不同for ,其用於其副作用循環。 通過使用適當的.combine函數,內部foreach循環可以返回向量,這些向量通過外部foreach循環按行方式組合成矩陣:

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

您還可以使用嵌套運算符: %:%

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

請注意, set.seed可能無法執行您想要的操作,因為它是在本地計算機上執行的,而隨機數是在不同的R會話中生成的,可能在不同的計算機上生成。

只是為Steve的回答添加一些內容:我認為關鍵點是並行后端啟動了多個Rscript.exe進程(可以在任務管理器中看到)。 foreach中使用的某些對象(即在您的情況下為x )將被復制到為每個進程分配的內存中。 我不確定如何在foreach包中處理復制,但是使用plyr包的*ply函數,您必須明確說明應該復制的對象。 不同的流程不共享他們的記憶。 (我不知道其他可以使用共享內存的R包......)

可以證明矩陣x實際上是通過使用.Internal(inspect(x))來打印對象x的內存位置來復制的。

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

你應該在那里找到兩個不同的內存地址。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM