【问题标题】:mclapply with lme4 and long vectorsmclapply 与 lme4 和长向量
【发布时间】:2018-06-20 11:07:46
【问题描述】:

我正在使用parallel 包中的mclapply 在高性能集群上使用lme4 包估计混合 glmer 模型。我遇到了described here 的问题。我应用了添加mc.preschedule=F 的建议修复,但问题仍然存在。代码设置为described here

我不确定如何解决它,有什么想法吗?我应该切换到另一种并行化方法吗?如果有,怎么做?

这是我的代码,但基本上它遵循链接文章的逻辑:

rm(list = ls())

require(lme4)
require(parallel)

load(file="//share//home//eborbath//ess_rescaled.Rda") # load data

# paralelizing function

f_lmer_mc = function(data, calls, mc.cores) {
  require(parallel)
  if (is.data.frame(data)) 
    data = replicate(length(calls), data, simplify = F)
  for (i in 1:length(data)) attr(data[[i]], "cll") = calls[i]
  m.list = mclapply(data, function(i) eval(parse(text = attr(i, "cll"))), 
                    mc.cores = mc.cores, mc.preschedule = FALSE)
  return(m.list)
}

##########
# Models #
##########


controls <- c("gender", "agea", "eduyrs", "domicil", "unemployed", "rideol", "union", "pid", "hincfel")
values <- c("conformity", "universalism", "security")
issues <- c("gincdif", "freehms")
agr.ctrl <- c("gdp_wb_ppp", "wb_vae")
lr.agr <- c("lr_rsquar_std", "ri_l2_std")
val.agr <- c("mean_univ", "mean_conf", "mean_secur")
end <- "1 + (1|cntry/countryyear), data=i, control=glmerControl(optimizer='bobyqa', optCtrl = list(maxfun = 1e9)), family=binomial(link='logit'))"

models = c(paste0("glmer(protest ~", paste(c(controls, end), collapse="+")),
paste0("glmer(protest ~", paste(c(controls, values, end), collapse="+")),
paste0("glmer(protest ~", paste(c(controls, values, issues, end), collapse="+")),
paste0("glmer(protest ~ region+", paste(c(controls, values, issues, end), collapse="+")),
paste0("glmer(protest ~ region+", paste(c(controls, values, issues, agr.ctrl, end), collapse="+")), 
paste0("glmer(protest ~ region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, end), collapse="+")),
paste0("glmer(protest ~ region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")), # until here it's only main effects
paste0("glmer(protest ~ region*rideol + region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")), 
paste0("glmer(protest ~ region*rideol*year + region+year+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")), 
paste0("glmer(protest ~ region*rideol*year_num + region+year_num+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")), 
paste0("glmer(protest ~ region*soc_pop_eleches + region+soc_pop_eleches+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")), # now come the expl. models
paste0("glmer(protest ~ region*rideol*soc_pop_eleches + region+soc_pop_eleches+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*ri_l2_std + region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*ri_l2_std*rideol + region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*lr_rsquar_std + region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*lr_rsquar_std*rideol + region+", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region+gov_genlr", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*gov_genlr + region+gov_genlr", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*gov_genlr*rideol + region+gov_genlr", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region+pol_galtan", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region+pol_galtan+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*pol_lrecon+region+pol_galtan+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*pol_galtan+region+pol_galtan+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*pol_lrecon*rideol+region+pol_galtan+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")),
paste0("glmer(protest ~ region*pol_galtan*rideol+region+pol_galtan+pol_lrecon", paste(c(controls, values, issues, agr.ctrl, lr.agr, val.agr, end), collapse="+")))

m.list = f_lmer_mc(data, models, 24)

m.1 <- c(m.list[1:3])
m.2 <- c(m.list[4:6])
m.3 <- c(m.list[7:9])
m.4 <- c(m.list[10:12])
m.5 <- c(m.list[13:15])
m.6 <- c(m.list[16:18])
m.7 <- c(m.list[19:21])
m.8 <- c(m.list[22:24])
m.9 <- c(m.list[25:26])

save(m.1, data, file='m_1.RData')
save(m.2, data, file='m_2.RData')
save(m.3, data, file='m_3.RData')
save(m.4, data, file='m_4.RData')
save(m.5, data, file='m_5.RData')
save(m.6, data, file='m_6.RData')
save(m.7, data, file='m_7.RData')
save(m.8, data, file='m_8.RData')
save(m.9, data, file='m_9.RData')

这是相关的错误信息:

Error in sendMaster(try(eval(expr, env), silent = TRUE)) : 
  long vectors not supported yet: fork.c:378
Calls: f_lmer_mc ... mclapply -> lapply -> FUN -> mcparallel -> sendMaster

谢谢!

更新:

数据是公开可用的European Social Survey 的清理版本。您可以从here (1.8 MB) 下载文件

【问题讨论】:

  • 这在没有数据的情况下很难分析。你能用随机数据重现这个问题吗?否则,您可以在本地运行一些模型并检查生成的对象。这些对象通常包含大型数据集,这些数据集在进一步向下不是严格必要的。在这种情况下,您可以在将对象发送回主对象之前将其从对象中删除。
  • 谢谢!你是对的,这是一个大型数据集。在我的机器上运行这些模型中的任何一个都需要几个小时。我已通过帖子末尾的链接提供了数据。
  • 我看到您正在复制数据集,然后将其发送到所有进程。我有一段时间没有做过并行的事情了,但你可能不需要这样做;小插图说“通过 mclapply,我们使用的所有包和对象都自动在工作人员身上可用。”如果是这样,那将负责处理流程,而 Ralf Stubner 的建议有望负责返回。
  • 老实说,我不太确定如何实施这些建议...意味着在发送回之前清理 lme4 输出或依靠 mcapply 处理流程?

标签: r parallel-processing lme4 mclapply


【解决方案1】:

我认为这个错误的发生是因为分叉的工作进程在序列化非常大的结果对象时遇到错误。我已经能够使用以下代码在 R 3.3.2 中重现此错误:

library(parallel)
r <- mclapply(1:2, function(i) 1:2^30, mc.cores=2, mc.preschedule=FALSE)

但是,此示例使用 64 位版本的 R 3.4.3 对我有用,因此在更高版本的 R 中似乎已删除(或至少增加了)序列化限制。

我建议您要么尝试将结果对象的大小减少到 2GB 以下,要么使用最新版本的 R。

【讨论】:

  • 谢谢!我会要求集群管理员这样做!
  • @eborbath,记录并更好地帮助将来报告相同错误的其他人,您在哪个版本的 R 中遇到了该错误?
  • 此限制记录在 R (>= 3.4.0) 中 - 在 ?parallel::mclapply 中它说“在 R 3.4.0 和 32 位平台上,每个分叉进程的序列化结果限制为 2^31 - 1 个字节。(通过序列化返回非常大的结果效率低下,应避免)。"
  • 我收到了R version 3.2.1 -- "World-Famous Astronaut"的错误
【解决方案2】:

扩展我上面的评论:

我看到您正在复制数据集,然后将其发送到所有 过程。我有一段时间没有做过并行的事情了,但你可能不会 需要这样做;小插图说“用 mclapply 所有的包和 我们使用的对象自动在工人身上可用。”如果是这样, 这将负责处理流程,以及 Ralf Stubner 的 建议希望能解决回来。

要尝试不复制数据,首先让调用使用data,正如您的load 调用所读取的那样,而不是i;你只需要改变这一行。

end <- "1 + (1|cntry/countryyear), data=data, control=glmerControl(optimizer='bobyqa', optCtrl = list(maxfun = 1e9)), family=binomial(link='logit'))"

然后让mclapply 运行这些,而不复制数据。

library(parallel)
m.list = mclapply(calls, function(i) eval(parse(text=i)), 
                  mc.cores = 2, mc.preschedule = FALSE)

为了尽量不返回模型中的所有信息(特别是每个模型的完整数据集),在查看glmer 输出后,我认为最好在流程中执行您想要的任何处理,而不是修改glmer 输出,因为修改glmer 输出可能会使之后更难获得您想要的摘要。这里我只得到摘要,并把它放在一个列表中,这样你也可以很容易地添加其他输出。

library(parallel)
m.list = mclapply(calls, function(i) {
                     a <- eval(parse(text=i))
                     list(summary=summary(a))
                  }, mc.cores = 2, mc.preschedule = FALSE)

请注意,这都是未经测试的......

【讨论】:

  • 非常感谢!
猜你喜欢
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
相关资源
最近更新 更多