使用 BiocParallel 运行 的并行处理比串行处理长得多

Parallel processing with BiocParallel running much longer than serial

我正在尝试使用并行处理来加速 运行R 中的许多增强回归树。我正在使用 BiocParallel 包 (http://lcolladotor.github.io/2016/03/07/BiocParallel/#.WiqF7bQ-e3c)。我创建了一些虚拟数据,然后为 运行 两个 BRT 模型设置了一个函数,我希望先串行然后并行计时。但是,我的并行 运行 似乎永远不会完成,而我的串行 运行 只需要大约 3 秒。

##CAN I USE PARALLEL PROCESSING TO SPEED UP BRT'S?

##LOAD PACKAGES
library(BiocParallel)
library(dismo)
library(gbm)
library(MASS)

##CREATE RANDOM, CORRELATED DATA
## FROM https://www.r-bloggers.com/simulating-random-multivariate-correlated-data-continuous-variables/
R = matrix(cbind(1,.80,.2,  .80,1,.7,  .2,.7,1),nrow=3)
U = t(chol(R))
nvars = dim(U)[1]
numobs = 100
set.seed(1)
random.normal = matrix(rnorm(nvars*numobs,0,1), nrow=nvars, ncol=numobs);
X = U %*% random.normal
newX = t(X)
raw = as.data.frame(newX)
orig.raw = as.data.frame(t(random.normal))
names(raw) = c("response","predictor1","predictor2")
cor(raw)


###########################################################
##  MODEL
##########################################################


##WITH FUNCTIONS, 

Tc<-c(4, 8) ##Tree Complexities

Lr<-c(0.01)  ## Learning Rates

Vars <- split(expand.grid(Tc,Lr),seq(nrow(expand.grid(Tc,Lr))))

brt <- function(x){
  a <- gbm.step(raw,gbm.x=c(2:3),gbm.y="response",tree.complexity=x[1],learning.rate=x[2],bag.fraction=0.65, family="gaussian")
  b <- data.frame(model=paste("Tc= ",x[1]," _ ","Lr= ",x[2],sep=""), R2=a$cv.statistics$correlation.mean, Dev=a$cv.statistics$deviance.mean)
  ##Reassign model with unique name
  assign(paste("patch.tc",x[1],".lr",x[2],sep=""),a, envir = .GlobalEnv)
  assign(paste("RESULTS","patch.tc",x[1],".lr",x[2],sep=""),b, envir = .GlobalEnv)
  print(b)
}



############################
###IN Serial
############################

system.time(
lapply(Vars, brt)
)


############################
###IN PARALLEL
############################

system.time(
bplapply(Vars, brt)
)

一些快速评论:

  1. 永远避免assign();如果您发现自己在使用它,则表明您正在以错误的方式解决问题。

  2. 从函数内将变量分配给全局环境(使用 assign()<<-)始终不是一个好主意,并且再次暗示有更好的解决方案你应该使用。

  3. 如果你还是选择打断上面的1和2,你用并行处理肯定不行

  4. 相反,return 您的价值观(见下文)。

  5. dismo::gbm.step() 函数默认尝试绘图 (plot.main = TRUE)。这在所谓的分叉并行处理中不起作用(实际上无效),这通常是 Unix 和 macOS 上的默认选择。

  6. 并行绘图通常不是您想要做的(除非您绘制图像文件或类似文件)。

针对你的问题:将你的brt()修改为(根据1-6):

brt <- function(x){
  a <- gbm.step(raw, gbm.x=c(2:3), gbm.y="response", tree.complexity=x[1], learning.rate=x[2], bag.fraction=0.65, family="gaussian", plot.main = FALSE)
  b <- data.frame(model=paste("Tc= ", x[1], " _ ", "Lr= ", x[2], sep=""), R2=a$cv.statistics$correlation.mean, Dev=a$cv.statistics$deviance.mean)
  list(a = a, b = b)
}

它适用于我 bplapply(Vars, brt) 以及 future::future_lapply(Vars, brt)。对于 parallel::parLapply(cl, Vars, brt),您需要更加小心地导出全局变量。

PS。我可能只是 return a 并在外部提取 b 信息。