snow包主要运行于传统的集群计算。它主要用于蒙特卡洛模拟(Monte Carlo simulations),boostrapping,交叉验证(cross validation),集成机器学习算法(ensemble machine learning algorithms)和K均值聚类(K-Means clustering)等,并且也很好支持并行随机数的生成。 snow包的安装一般应用install.packages('snow')
. 要使用snow包进行并行运算,首先要创建一个集群对象,主要用于与内核的交互,一般传递与snow包中函数的第一个参数。 基本的集群创建函数为makeCluster(),它能创建任何类型的集群,例如,在本地机器上创建一个4核的集群:
第一个参数为集群设定,即设定使用的CPU数;第二个参数是集群类型。 注意:在结束集群时使用stopCluster()
。 下面使用snow包做一个并行运算。
数据是MASS包自带的Boston数据集。 K均值函数使用stats包中的kmeans()。
library(MASS)result <- kmeans(Boston, 4, nstart = 100)在使用并行计算前,首先看看使用lapply函数的运行情况
results <- lapply(rep(25,4), function(nstart) kmeans(Boston, 4, nstart = nstart)i <- sapply(results, function(result) result$tot.withiness)result <- results[[which.min(i)]]相比较clusterEvalQ
而言,clusterCall
更好用,它的第一个参数为集群对象,第二个参数为一个函数,并且其他的参数可以传递给这个函数。最终返回一个列表。
clusterCall函数可以调用多个包,
worker.init <- function(packages) {for (p in packages) {library(p, character.only=TRUE)}NULL}clusterCall(cl, worker.init, c('MASS', 'boot'))character.only=TRUE
是使library把参数解释为字符向量,否则library会重复载入名称为p的包。
clusterApplyLB与clusterApply函数相似,但clusterApplyLB的运行效率更高。在使用clusterApply并行运算时,如果每一个内核花费不同的时间进行运算,那么在那个运行时间长的内核结束之前,运行时间短的内核不能进行下一次运算,而clusterApplyLB不同,它是在运行时间短的内核结束之后接着就运行下一次的运算,这样就减少了时间的浪费,因此提高了效率。 为了说明clusterApplyLB的效率,我们使用控制任务时间长度的函数Sys.sleep。用snow.time收集整个执行过程的时间信息。
set.seed(7777442)sleeptime <- abs(rnorm(10, 10, 10))tm <- snow.time(clusterApplyLB(cl, sleeptime, Sys.sleep))plot(tm)作为对照,我们用clusterApply函数来观察运行时间
tm1 <- snow.time(clusterApply(cl, sleeptime, Sys.sleep))plot(tm1)由此看出clusterApplyLB效率更高。
parLapply是snow包中的一个高级函数,它比clusterApply函数更高效,如果参数x的长度与内核的数量相等,parLapply的优势不明显,如果参数x的长度远大于内核的数量,parLapply相比于clusterApply是一个更好的选择。 应用一个并行休眠函数的用法,首先使用clusterApply
bigsleep <- function(sleeptime, mat) Sys.sleep(sleeptime)bigmatrix <- matrix(0, 2000, 2000)sleeptime <- rep(1, 100)tm2 <- snow.time(clusterApply(cl, sleeptime, bigsleep, bigmatrix))plot(tm2)由图看出并不高效,因为有大量的输入输出时间,下面再试一试clusterApplyLB:
tm3 <- snow.time(clusterApplyLB(cl, sleeptime, bigsleep, bigmatrix))plot(tm3)由上图看出,运算集中在第1、2和3个内核上,第4个内核上运算的时间非常少,及运算效率差,但总体还是比clusterApply函数要好一些。 看看最终的函数parLapply:
tm4 <- snow.time(parLapply(cl, sleeptime, bigsleep, bigmatrix))plot(tm4)由此看出,传输交换的时间大大缩短了,因此提高了效率。
新闻热点
疑难解答