终于!最近在做代码优化的时候发现部分代码可以使用并行化实现,太多重复工作,于是决定使用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了,为什么还提示没有。。。

  1. 最简单用法
foreach(a=1:3, b=rep(10, 3)) %do% {
  a + b
}

不是并行,类似lapply功能

lapply(cbind(1:3,rep(10,3),function(x,y) x+y ))
  1. 并行
    话不多说,直接并行,学这个不就是为了它吗。
    首先要检测计算机环境的核心数
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)
}

随便写的,可能没什么含义,意思到了就行!