jos*_*r83 9 parallel-processing foreach r
我试图在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.
}
}
Run Code Online (Sandbox Code Playgroud)
我想编码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
Run Code Online (Sandbox Code Playgroud)
但是,我似乎无法弄清楚如何更新阵列.我试过把x <-它放到其他地方,但它似乎不喜欢它.我认为这将是一个非常容易解决的问题,但我所有的搜索还没有把我带到那里.谢谢.
Ste*_*ton 15
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
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用嵌套运算符%:%::
x <- foreach(i=1:8, .combine='rbind') %:%
foreach(j=1:2, .combine='c') %dopar% {
l <- runif(1, i, 100)
i + j + l
}
Run Code Online (Sandbox Code Playgroud)
请注意,set.seed可能无法执行您想要的操作,因为它是在本地计算机上执行的,而随机数是在不同的R会话中生成的,可能在不同的计算机上生成.
只是为了在 Steve 的答案中添加一些内容:我认为关键点是并行后端启动多个 Rscript.exe 进程(如任务管理器中所示)。然后,在中使用的某些对象foreach(即在您的情况下x)将被复制到为每个进程分配的内存中。我不确定包中如何处理复制foreach,但是使用包*ply的功能,plyr您必须显式声明应该复制的对象。不同的进程不共享它们的内存。(我不知道其他 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)
Run Code Online (Sandbox Code Playgroud)
矩阵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,..."
...
Run Code Online (Sandbox Code Playgroud)
您应该在那里找到两个不同的内存地址。