mclapply с lme4 и длинными векторами
Я использую mclapply
от parallel
пакет для оценки моделей смешанного блеска с использованием lme4
пакет на высокопроизводительном кластере. У меня проблема, описанная здесь. Я применяю предложенное исправление добавления mc.preschedule=F
, но проблема сохраняется. Код настроен как описано здесь.
Я не уверен, как обойти это, какие-либо идеи? Должен ли я перейти на другой метод распараллеливания? если да, то как?
Это мой код, но в основном он соответствует логике связанных статей:
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
Спасибо!
ОБНОВИТЬ:
Данные представляют собой очищенную версию общедоступного Европейского социального опроса. Вы можете скачать файл здесь (1,8 МБ)
2 ответа
Я думаю, что эта ошибка происходит из-за того, что разветвленные рабочие процессы получают ошибку при сериализации очень больших объектов результатов. Я смог воспроизвести эту ошибку в 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.
Я предлагаю вам либо попытаться уменьшить размер получаемых объектов до размера менее 2 ГБ, либо использовать самую последнюю версию R.
Расширяя мой комментарий выше:
Я вижу, вы реплицируете набор данных и затем отправляете его всем процессам. Я давно не занимался параллельными вещами, но вам, возможно, не нужно это делать; Виньетка гласит: "Благодаря mclapply все используемые нами пакеты и объекты автоматически становятся доступными для рабочих". Если это так, то это позаботится о том, чтобы перейти к процессам, и, надеюсь, предложение Ральфа Стубнера позаботится о возвращении.
Чтобы не реплицировать данные, сначала используйте вызовы 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)
Обратите внимание, что это все не проверено...