我最近有一台带有多个内核的计算机,我正在学习使用并行计算.我非常精通lapply
并被告知parLapply
工作非常相似.我虽然没有正确操作.似乎我必须明确地将所有内容放在其中parLapply
以使其工作(即要使用的函数,变量等).使用lapply
它从父环境读取,parLapply
似乎不这样做.所以在我下面的例子中,我可以通过将所有信息放在里面来使一切工作,parLapply
但如果我在用户定义的函数中使用它,我就无法明确地放入text.var
其中parLapply
.
library(parallel)
text.var <- rep("I like cake and ice cream so much!", 20)
ntv <- length(text.var)
gc.rate <- 10
pos <- function(i) {
paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
}
lapply(seq_len(ntv), function(i) {
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}
)
#doesn't work
cl <- makeCluster(mc <- getOption("cl.cores", 4))
parLapply(cl, seq_len(ntv), function(i) {
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}
) …
Run Code Online (Sandbox Code Playgroud) 从命令行或脚本使用 jags.parallel 工作正常。我可以从http://www.inside-r.org/packages/cran/R2jags/docs/jags运行这个修改过的例子就好了
# An example model file is given in:
model.file <- system.file(package="R2jags", "model", "schools.txt")
#=================#
# initialization #
#=================#
# data
J <- 8.0
y <- c(28.4,7.9,-2.8,6.8,-0.6,0.6,18.0,12.2)
sd <- c(14.9,10.2,16.3,11.0,9.4,11.4,10.4,17.6)
jags.data <- list("y","sd","J")
jags.params <- c("mu","sigma","theta")
jags.inits <- function(){
list("mu"=rnorm(1),"sigma"=runif(1),"theta"=rnorm(J))
}
#===============================#
# RUN jags and postprocessing #
#===============================#
# jagsfit <- jags(data=jags.data, inits=jags.inits, jags.params,
# n.iter=5000, model.file=model.file)
# Run jags parallely, no progress bar. R may be frozen for a while,
# Be patient. Currenlty …
Run Code Online (Sandbox Code Playgroud) 这可能是哲学家的一个……(或@Steve Weston 或@Martin Morgan)
我在使用 parLapply 时遇到了一些内存泄漏问题,在深入研究了足够多的线程后,我认为这个问题是有道理的。我花了一些时间来尝试解决这个问题,虽然我对观察到的行为发生的原因有所了解,但我不知道如何解决它。
将以下内容视为源脚本,另存为: parallel_question.R
rf.parallel<-function(n=10){
library(parallel)
library(randomForest)
rf.form<- as.formula(paste("Final", paste(c('x','y','z'), collapse = "+"), sep = " ~ "))
rf.df<-data.frame(Final=runif(10000),y=runif(10000),x=runif(10000),z=runif(10000))
rf.df.list<-split(rf.df,rep(1:n,nrow(rf.df))[1:nrow(rf.df)])
cl<-makeCluster(n)
rf.list<-parLapply(cl,rf.df.list,function(x,rf.form,n){
randomForest::randomForest(rf.form,x,ntree=100,nodesize=10, norm.votes=FALSE)},rf.form,n)
stopCluster(cl)
return(rf.list)
}
Run Code Online (Sandbox Code Playgroud)
我们使用以下命令获取并运行脚本:
scrip.loc<-"G:\\Scripts_Library\\R\\Stack_Answers\\parallel_question.R"
source(scrip.loc)
rf.parallel(n=10)
Run Code Online (Sandbox Code Playgroud)
相当直接……我们并行运行了几个随机森林。似乎是内存效率。我们可以稍后将它们组合起来,或者做其他事情。便利。好的。表现得很好。
现在考虑以下脚本,另存为 parallel_question_2.R
rf.parallel_2<-function(n=10){
library(parallel)
library(magrittr)
library(randomForest)
rf.form<- as.formula(paste("Final", paste(c('x','y','z'), collapse = "+"), sep = " ~ "))
rf.df<-data.frame(Final=runif(10000),y=runif(10000),x=runif(10000),z=runif(10000))
large.list<-rep(rf.df,10000)
rf.df.list<-split(rf.df,rep(1:n,nrow(rf.df))[1:nrow(rf.df)])
cl<-makeCluster(n)
rf.list<-parLapply(cl,rf.df.list,function(x,rf.form,n){
randomForest::randomForest(rf.form,x,ntree=100,nodesize=10, norm.votes=FALSE)},rf.form,n)
stopCluster(cl)
return(rf.list)
}
Run Code Online (Sandbox Code Playgroud)
在第二个脚本中,我们在源代码环境中有一个很大的列表。我们不会调用列表或将其带入我们的并行函数中。我已将列表的大小设置为在至少 32GB 的机器上可能是个问题。
scrip.loc<-"G:\\Scripts_Library\\R\\Stack_Answers\\parallel_question_2.R"
source(scrip.loc)
rf.parallel_2(n=10)
Run Code Online (Sandbox Code Playgroud)
当我们运行第二个脚本时,我们最终携带了大约 3gb(我们的大列表的大小)* 设置到集群的工作线程数,以及额外的材料。如果我们在无源环境中运行第二个脚本的内容,则不会出现这种行为;相反,我们得到一个 ~3gb 的列表,并行化的函数运行没有问题,这就是它的结束。
那么..如何/为什么工作环境从父环境中获取不必要的变量元素?为什么它只发生在源脚本中?当我有一个源代码、大型且复杂的脚本,其中包含并行化的子部分(但可能有 3-10gb 的中间数据被携带)时,我该如何缓解这种情况?
相关或类似的主题: