并行化你的运算-初识parallel包
R 2.14.0版本今后,parallel包被作为焦点包引入R,这个包主要成立在 multicore 和 snow 包的事情基本之上,包括了这两个包大部门成果函数,以及集成了随机数产生器。
实际上对付R来说,并行化可以在差异的层级上实现:好比,在最底层,此刻的多核CPU可以实现一些基本的数值运算(好比整数和浮点算数);高级一点的,一些扩展BLAS包利用多线程并行处理惩罚向量和矩阵的操纵,甚至有些R扩展包,通过挪用OpenMP(注释1)或pthreads来利用C 级此外多线程方法。
本文的主角,parallel包却是从别的角度的实现,简朴说是一种“粗粒度”的并行化方法。在我们的日常事情中会碰着一下环境:
对付第一种环境,一般会回收显式轮回或隐式轮回的方法,但惋惜的是R并不能识别这是并行计较,依旧凭据串行的方法举办处理惩罚。第二种环境,如蒙特卡洛模仿,但在同一个R历程中,所有的运算都是按顺序举办的,能做的就是多开几个R,将各个运算人工分派,最后手工归并功效,囧
我们再仔细思量一下第一种环境(第二种环境也雷同),要害在于这些计较并不关联,可能说不需要举办通讯。这样的计较进程可以利用如下方法来表述:
- 启动M个隶属历程,并初始化
- 针对付任务,为每个隶属历程分发所有的数据
- 将任务大致的分为M个块儿(chunks),并将这些块儿发送到隶属历程(包括需要的R代码)
- 期待所有的隶属历程完成计较任务,并返回功效
- 对付其他任务也同样反复2-4
- 封锁隶属历程
对付上述的并行化方法,隶属历程可以利用如下方法构建:
虽然,对付这两种并行化方法,的R自带的parallel包都有支持。尚有一种是通过OS级的通讯方法,好比PVM (`parallel virtual machine’),以及SGE等,同样有相关的技能和包来支持,这里不再展开接头。
我们此刻说一些实际的,如安在实际项目应用中利用并行化计较方法来提高我们的事情效率。在parallel包里,对应上述两种并行化方法有如下两个焦点函数(针对付lapply函数的并行化,mclapply在windows上不能利用):
思量 lapply这个函数,这种隐式轮回函数,它实际就是对差异的数据应用了沟通的函数,是可以并行化的。首先看一个例子:
doit <- function(x)(x)^2 + 2*x
system.time(res <- lapply(1:5000000, doit))
user system elapsed
24.05 0.05 24.20
上述lapply的表达同一个for轮回没什么两样,但由于数据集较量大,500w,所以耗损的时间相对较长。我们利用parallel包来加快:
library(parallel)
cl <- makeCluster(getOption(“cl.cores”, 3)) # use 3 cores
system.time(res <- parLapply(cl, 1:5000000, doit))
user system elapsed
6.54 0.34 19.95
stopCluster(cl) # close clusters
运行parLapply的时候,处理惩罚器三个焦点瞬间占满,很快就将功效返回。不外这个函数有两点要留意:
- 首先要先用detectCores函数确定系统焦点数目,对付Window系统下的Intel I5或I7 处理惩罚器,一般利用detectCores(logical = F)来得到实际的物理焦点数量。
- 由于这个函数利用的是挪用Rscript的方法,这个例子里,工具被复制了三份,因此内存会吃的很锋利,在大数据条件就要小心利用
在Linux下利用mclapply函数的结果如下:
mc <- getOption(“mc.cores”, 3)
system.time(res <- mclapply(1:5000000, doit, mc.cores = mc))
user system elapsed
6.657 0.500 7.181
除了对付lapply,sapply这类函数的并行化外,parallel包尚有针对付apply的并行化函数,好比parApply,以及种种动态均衡的函数如parLapplyLB,请拜见parallel包的辅佐文档。
注释1:OpenMP (Open Multiprocessing) is an API that supports multi-platform shared memory multiprocessing programming in C,C++, and Fortran, on most processor architectures and operating systems.