R 语言本身计算速率相对慢,且 CRAN 提供 的 R 本身对于并行计算的支持相对不如 python 那么方便。为了提高计算速度, 可以利用 snow 包来做 并行计算。在较新的核心 R 包中已经加入了基于 snow 包的 parallel 包,可 以直接使用 parallel 包。Snow 包也是 BiocParallel 等方便进行并行计算的包的基础。Snow 采用类似集群的方法来管理并行计算。
开启和结束集群
创建计算节点:
> cl <- makeCluster(2, type='SOCK')
默认的节点类型是 SOCK,如果机器上支持 MPI,还可以指定节点类型。
> cl <- makeCluster(2, type='MPI')
关闭计算节点:
> stopCluster(r)
在节点计算
snow 提供了方便的,在创建好的节点进行计算的函数。
主要的通用计算命令有如下几个:
clusterSplit(cl, seq)
clusterCall(cl, fun, ...)
clusterApply(cl, x, fun, ...)
clusterApplyLB(cl, x, fun, ...)
clusterEvalQ(cl, expr)
clusterExport(cl, list, envir = .GlobalEnv)
clusterMap(cl, fun, ..., MoreArgs = NULL, RECYCLE = TRUE)
向节点传递环境变量
计算节点中本身是没有主近程中的变量和加载的包的,clusterExport
可以把
环境变量传送到计算节点,clusterEvalQ
可以在计算节点运行命令。
> clusterEvalQ(cl, library(ggplot2))
可以实现在计算节点中加载ggplot2
包。
> myfunc <- function() {1 + 1}
> clusterExport(cl, 'myfunc')
可以使得节点中也有自定义的myfunc
函数。
并行的 split 函数
R 中的 split
函数可以把一个向量分成若干个,clusterSplit
函数可以把
向量在不同的节点上进行平均分配,返回一个长度和节点数量一致的 list。
并行的 call 函数
可以在节点并行 call 函数。首先可以创建一个需要运行的函数:
> myfunc <- function(a) {print(a)}
然后利用 clusterCall
进行计算:
> clusterCall(cl, myfunc, 'myfunc')
clusterCall(cl, fun, ...)
的 cl
为创建的集群,fun
为需要计算的函
数,之后是函数输入的参数。
Apply 函数
clusterApply
和 clusterApplyLB
都是对一个 list 或者 vector 进行并
行计算,也是下面提到的各种并行的 Apply 函数的基础。clusterApplyLB
相
对于 clusterApply
的区别在于,clusterApplyLB
对于超过节点数的 list
或者 vector 的计算采用了更好的分配方法,会在计算好的节点加入新的计算任
务,LB是load balance的缩写。而 clusterApply
则是按照顺序循环利用节点。
> clusterApply(cl, 1:3, `^`, 2)
snow 提供了在 R 中常用的 lapply
,sapply
,apply
函数的并行计算的
包装,分别为 parLapply
,parSapply
,parApply
,基本参数和lapply
,
sapply
,apply
都一致。同时,parallel 包还提供了load balance版的
parLapplyLB
,parSapplyLB
。为了方便使用,对于 apply
函数的
MARGIN=1
和 MARGIN=2
,snow 包还提供了 parRapply
来对行进行分割并
行计算,parCapply
来对列进行分割并行计算。
parLapply(cl = NULL, X, fun, ..., chunk.size = NULL)
parSapply(cl = NULL, X, FUN, ..., simplify = TRUE,
USE.NAMES = TRUE, chunk.size = NULL)
parApply(cl = NULL, X, MARGIN, FUN, ..., chunk.size = NULL)
parRapply(cl = NULL, x, FUN, ..., chunk.size = NULL)
parCapply(cl = NULL, x, FUN, ..., chunk.size = NULL)
parLapplyLB(cl = NULL, X, fun, ..., chunk.size = NULL)
parSapplyLB(cl = NULL, X, FUN, ..., simplify = TRUE,
USE.NAMES = TRUE, chunk.size = NULL)