繁体   English   中英

在使用doMC的并行仿真研究中需要有关合并功能的帮助

[英]Need help on combine function in a Parallel Simulation study using doMC

我想寻求有关为foreach()编写合并函数的帮助。 考虑以下功能:

library(mvtnorm)
library(doMC)

mySimFunc <- function(){
  myNum <- runif(1)
  myVec <- rnorm(10)
  myMat <- rmvnorm(5, rep(0, 3), diag(3))
  myListRslt <- list("myNum" = myNum, "myVec" = myVec, "myMat" = myMat)
return (myListRslt)
}

现在,我想使用foreach()%dopar%将上面的代码运行1000次,并且在每次迭代中我都希望:

  1. 按原样返回myNum
  2. 获取myVec的平均值并返回
  3. 获取myMat的colMeans()并将其返回。

我希望foreach()%dopar%返回最终列表,包括:

  1. 长度为1000的向量,包括1000 myNum,每个向量对应于一个迭代
  2. 长度为1000的向量,其中每次迭代均包含1000的myVec平均值
  3. 包含1000行的矩阵,其中每一行都包含该迭代中myMat的colMeans

我理想的解决方案

我的理想解决方案是找到foreach()的行为与之完全相同的方法,以便我可以简单地定义:

myNumRslt <- NULL
myVecRslt <- NULL
myMatRslt <- NULL

# and then simply aggregate result of each iteration to the variables above as:
foreach(i = 1:1000) %dopar%{
   rslt <- mySimFunc()
   myNumRslt <- c(myNumRslt, rslt$myNum)
   myVecRslt <- c(myVecRslt, mean(rslt$myVec))
   myMatRslt.tmp <- colMeans(rslt$myMat)
   myMatRslt <- rbind(myMatRslt, myMatRslt.tmp)
}

但是,不幸的是,似乎不可能使用foreach()来做到这一点,因此我认为唯一的解决方案是编写一个与上述结果汇总相似的Combine函数。

挑战

1)我如何编写一个合并函数,返回上面解释的内容?

2)当我们执行%dopar%(假设使用doMC软件包)时,doMC是否将每个迭代分配给CPU,或者它进一步将每个迭代划分为更多部分并进行分配?

3)有没有比使用doMC和foreach()更好(更有效)的方法? 想法在这个问题 布赖恩提到一个辉煌的方式来对付列表,包括数值。 就我而言,我具有数值以及向量和矩阵。 我不知道该如何扩展Brian的想法。

非常感谢您的帮助。

编辑

使用.combine清理的通用解决方案:

#modify function to include aggregation
mySimFunc2 <- function(){
myNum <- runif(1)
myVec <- mean(rnorm(10))
myMat <- colMeans(rmvnorm(5, rep(0, 3), diag(3)))
myListRslt <- list("myNum" = myNum, "myVec" = myVec, "myMat" = myMat)
return (myListRslt)
}

#.combine function
MyComb1 <- function(...) {
lst=list(...)
vec<-sapply(1:length(lst), function (i) return(lst[[i]][[1]] ))
vecavg<-sapply(1:length(lst),function (i) return(lst[[i]][[2]] ))
colmeans<-t(sapply(1:length(lst), function (i) return(lst[[i]][[3]])))
final<-list(vec,vecavg,colmeans)
names(final)<-c("vec","vecavg","colmeans")
return(final)
}

library(doParallel)
cl <- makeCluster(3) #set cores
registerDoParallel(cl)

foreach(i=1:1000,.export=c("mySimFunc2","MyComb1"),.combine=MyComb1,
.multicombine=TRUE,.maxcombine=1000, .packages=c("mvtnorm"))%dopar%{mySimFunc2()}

现在,您应该具有一个包含所需三个对象的列表输出,我分别将其命名为vecvecavgcolmeans 请注意,如果迭代次数大于100,则必须将.maxcombine设置为迭代次数。

附带说明一下,尽管我猜测实际的任务可能会更复杂,但对于此示例任务进行并行化没有任何意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM