终于!最近在做代码优化的时候发现部分代码可以使用并行化实现,太多重复工作,于是决定使用parallel
包和doRNG
包实现。
话不多说,直接导入包:
library("foreach")
library("doParallel")
library("doRNG")
foreach
比传统apply
组函数的优越之处在于,它可以通过调用操作系统的多核运行性能来执行并行任务,这样特别是对于I/O密集型任务而言,可以大大节省代码执行效率。
我们来看一下用法:
foreach(..., .combine, .init, .final=NULL, .inorder=TRUE,
.multicombine=FALSE,
.maxcombine=if (.multicombine) 100 else 2,
.errorhandling=c('stop', 'remove', 'pass'),
.packages=NULL, .export=NULL, .noexport=NULL,
.verbose=FALSE)%dopar%{f(x)}
参数解释:
- %do%是按顺序执行,不是并行计算!之前吃了好久的坑,%dopar%才是,速度会快很多
- .combine:运算之后结果的显示方式,default是list,“c”返回vector, cbind和rbind返回矩阵
- .packages:指定在%dopar%运算过程中依赖的package(%do%会忽略这个选项),用于并行一些机器学习算法。
- .export:在编译函数的时候依赖的变量,比如自定义的函数、数据集啥的
注意:每次并行化是独立运行的,所以不管你什么时候、是否在全局环境中调用了某函数或者某变量等等,都需要在.packages
和.export
中加上,当然你可以有其他的解决方案,这种是最方便的!!
如果你没有做这个,你就会发现报错:找不到xxx函数!!!各种找不到,然后你肯定会疑惑:我明明load、source了,为什么还提示没有。。。
- 最简单用法
foreach(a=1:3, b=rep(10, 3)) %do% {
a + b
}
不是并行,类似lapply功能
lapply(cbind(1:3,rep(10,3),function(x,y) x+y ))
- 并行
话不多说,直接并行,学这个不就是为了它吗。
首先要检测计算机环境的核心数
n_cores <- detectCores() - 1
最好保留一个,做人留一线,日后好相见!
然后构建集群
cl <- makeCluster(n_cores)
最后注册并行化
doParallel::registerDoParallel(cl, cores = n_cores)
好了,你已经学会了,现在直接foreach就完事了。
最后不要忘记了,每次并行化代码要加上
parallel::stopCluster(cl)
不然你的环境核心还一直没有被收回,只剩一个核了😂。
来个简单的例子看看:
i <- NULL
n_cores <- detectCores() - 1
cl <- makeCluster(n_cores)
doParallel::registerDoParallel(cl, cores = n_cores)
res <- foreach(i= 2:4,
.combine = c,
.packages="randomForest",
.export = "base"
) %dopar% {
try({
base^exponent
randomForest(x, y, ntree=ntree)
})
}
parallel::stopCluster(cl)
}
随便写的,可能没什么含义,意思到了就行!