Foreach代码适用于%do%但不适用于%dopar%

时间:2016-02-09 20:50:21

标签: r foreach

这在我的电脑上正常运行:

registerDoSNOW(makeCluster(2, type = "SOCK"))

foreach(i = 1:M,.combine = "c") %dopar% {

  sum(rnorm(M))
  }

所以我可以说我可以在这台计算机上运行并行化代码,对吗?

确定。我有一段代码,我希望与 foreach 并行运行。它用%do%写的时候运行得很好,但是当我把它改成%dopar%时它不能正常工作。 (PS:我已经使用registerDoSNOW(makeCluster(2, type = "SOCK"))以与以前相同的方式初始化了群集。)

我对代码的主要兴趣是获取向量 u.varpred 。我很好地使用%do%,但是当我用%dopar%运行它时,向量变为NULL。

这是一个循环,其中包含正确运行所需的代码。它使用 geoR 包中的函数。

#you can pretty much ignore all this, it's just preparation for the loop
N=20
NN=10 

set.seed(111);
datap <- grf(N, cov.pars=c(20, 5),nug=1) 

grid.o <- expand.grid(seq(0, 1, l=100), seq(0, 1, l=100))
grid.c <- expand.grid(seq(0, 1, l=NN), seq(0,1, l=NN)) 

beta1=mean(datap$data)
emv<- likfit(datap, ini=c(10,0.4), nug=1) 
krieging <- krige.conv(datap, loc=grid.o,
                       krige=krige.control(type.krige="SK", trend.d="cte",
                                           beta =beta1, cov.pars=emv$cov.pars))



names(grid.c) = names(as.data.frame(datap$coords))
list.geodatas<-list()
valores<-c(datap$data,0)
list.dataframes<-list()

list.krigings<-list(); i=0; u.varpred=NULL;

#here is the foreach code
t<-proc.time()
foreach(i=1:length(grid.c[,1]), .packages='geoR') %do% {
  list.dataframes[[i]] <- rbind(datap$coords,grid.c[i,]);
  list.geodatas[[i]] <- as.geodata(data.frame(cbind(list.dataframes[[i]],valores)))
  list.krigings[[i]] <- krige.conv(list.geodatas[[i]], loc=grid.o,
                                   krige=krige.control(type.krige="SK", trend.d="cte",
                                                       beta =beta1, cov.pars=emv$cov.pars));
  u.varpred[i] <- mean(krieging$krige.var - list.krigings[[i]]$krige.var)
  list.dataframes[[i]]<-0 #i dont need those objects anymore but since they
  # are lists i dont want to put <-NULL as it'll ruin their ordering
  list.krigings[[i]]<- 0 
  list.geodatas[[i]] <-0
}
t<-proc.time()-t
t

您可以检查这是否运行良好(前提是您有以下软件包: geoR foreach doSNOW )。但是,一旦我使用registerDoSNOW(......)%dopar% u.varpred 就会显示为NULL。

你们可以试着看看我是否在foreach声明/过程中犯了错误,或者它是否只是不能并行的代码? (我认为可以,因为任何给定的迭代都不会在它之前的任何迭代上降低..)

我很抱歉代码和这个问题都很长。提前感谢您花时间阅读它。

1 个答案:

答案 0 :(得分:2)

我的朋友直接帮助了我。这是一种有效的方式:

    u.varpred <- foreach(i = 1:length(grid.c[,1]), .packages = 'geoR', .combine = "c") %dopar% {
  list.dataframes[[i]] <- rbind(datap$coords,grid.c[i,]);
  list.geodatas[[i]] <- as.geodata(data.frame(cbind(list.dataframes[[i]],valores)));
  list.krigings[[i]] <- krige.conv(list.geodatas[[i]], loc = grid.o,
                        krige = krige.control(type.krige = "SK", trend.d = "cte",
                        beta = beta1, cov.pars = emv$cov.pars));
  u.varpred <- mean(krieging$krige.var - list.krigings[[i]]$krige.var);
  list.dataframes[[i]] <- 0; 
  list.krigings[[i]] <- 0;
  list.geodatas[[i]] <- 0;
  u.varpred #this makes the results go into u.varpred
}

他举了一个例子说明了为什么会这样:

a <- NULL
foreach(i = 1:10) %dopar% {
  a <- 5
}
print(a)
# a is still NULL

a <- NULL
a <- foreach(i = 1:10) %dopar% {
  a <- 5
  a
}
print(a)
#now it works

希望这有助于任何人。