3

我使用 R 中的包在单独的处理节点上运行每个链的贝叶斯统计模型runjags。我想通过使用包在并行循环中嵌套run.jags调用来一次拟合多个模型foreach。但是,这通常会导致错误消息,可能是因为foreach循环不“知道”在循环内我正在调用其他并行进程,因此内核可能是双重分配的(或其他什么)。这是一个示例错误消息:

{ 中的错误:任务 2 失败 -“尝试运行 JAGS 模型时遇到以下错误:socketConnection
中的错误(“localhost”,端口 = 端口,服务器 = TRUE,阻塞 = TRUE,:无法打开连接

这是一些示例代码,用于生成数据并拟合两个模型,每个模型请求 2 个内核(总共需要 4 个内核,我的笔记本电脑上有)。我很想找到一个解决方案,让我可以并行运行多个并行 JAGS 模型。实际上,我一次在集群上运行 5-10 个模型,每个模型需要 3 个内核。

library(foreach)
library(runjags)

#generate a random variable, mean of 25, sd = 5.----
y.list <- list()
for(i in 1:2){
  y.list[[i]] <- rnorm(100, 25, sd = 5)
}

#Specify a JAGS model to fit an intercept.----
jags.model = "
model{
  for(i in 1:N){
    y.hat[i] <- intercept
    y[i] ~ dnorm(y.hat[i], tau)
  }

  #specify priors.
  intercept ~ dnorm(0,1E-3)
  tau <- pow(sigma, -2)
  sigma ~ dunif(0, 100)
}
"

n.cores <- 4
registerDoParallel(n.cores)

#Fit models in parallel, with chains running in parallel.----
#two processes that each require two cores (4 cores are registered and all that is required.)
output <- list()
output <- 
foreach(i = 1:length(y.list)) %dopar% {
    #specify data object.
    jd <- list(y=y.list[[i]], N = length(y.list[[i]]))
    #fit model.
    jags.out <- run.jags(jags.model,
                         data=jd,
                         n.chains=2,
                         monitor=c('intercept','tau'),
                         method='rjparallel')
    #return output
    return(jags.out)
}
4

2 回答 2

2

我无法运行您的示例,但以下小插图应该可以帮助您。

您可能想尝试使用 foreach 嵌套运算符 %:%

https://cran.r-project.org/web/packages/foreach/vignettes/nested.pdf

foreach(i = 1:length(y.list)) %:% {
    #specify data object.
    jd <- list(y=y.list[[i]], N = length(y.list[[i]]))
    #fit model.
    jags.out <- run.jags(jags.model,
                         data=jd,
                         n.chains=2,
                         monitor=c('intercept','tau'),
                         method='rjparallel')
    #return output
    return(jags.out)
}
于 2018-12-03T16:34:12.727 回答
2

这里有两件事要考虑——一般来说如何嵌套并行foreach()循环,以及如何解决这个特定问题。

嵌套并行foreach()循环的解决方案来自@Carlos Santillan 下面的回答,并且基于可以在此处找到的小插图。假设我们有一个内部循环嵌套在一个外部循环中,类似于上面的问题,但是run.jags我们有一个并行调用而不是并行foreach()调用:

outer_list <- list()
#begin outer loop:
outer_list <-
foreach(i = 1:length(some_index)) %:% {
    #grab something to feed next foreach loop.
    to_inner <- grab_data[[i]]

    #Do something in a nested foreach loop.
    inner_list <- list()
    #begin inner loop:
    inner_list <-
    foreach(k = 1:some_index) %dopar% {
      #do some other function.
      out_inner <- some_function(to_inner)
      return(out_inner)
      }
   out_outer <- some_function(out_inner)
   return(out_outer)
}

关键是%:%在外循环中使用运算%dopar%符,在内循环中使用运算符。

然而,这并不能解决上述run.jags()嵌套并行问题,因为它不是嵌套foreach()循环。为了解决这个特殊的嵌套run.jags()问题,我将methodrun.jags 中的设置更改为method=parallel而不是method=rjparallel. run.jags()有多种不同的并行实现,这个特定的实现似乎基于我的时序分析。希望将来会有一个更明确的答案来解释为什么会这样。我只知道它确实有效。

于 2018-12-04T01:51:34.543 回答