R语言并行运算(snow包)

本文介绍了R语言snow包在并行运算中的应用,包括使用clusterApply、clusterApplyLB和parLapply进行K均值聚类的并行计算。通过对比,展示了clusterApplyLB在效率上的优势,并探讨了parLapply在处理大量数据时的高效性。文中还提供了示例代码,展示了如何创建集群、并行调用函数以及如何减少传输交换时间提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击下方图片查看HappyChart专业绘图软件

HappyChart专业绘图软件

snow包

snow包主要运行于传统的集群计算。它主要用于蒙特卡洛模拟(Monte Carlo simulations),boostrapping,交叉验证(cross validation),集成机器学习算法(ensemble machine learning algorithms)和K均值聚类(K-Means clustering)等,并且也很好支持并行随机数的生成。
snow包的安装一般应用install.packages('snow').
要使用snow包进行并行运算,首先要创建一个集群对象,主要用于与内核的交互,一般传递与snow包中函数的第一个参数。
基本的集群创建函数为makeCluster(),它能创建任何类型的集群,例如,在本地机器上创建一个4核的集群:

cl <- makeCluster(4, type="SOCK")

第一个参数为集群设定,即设定使用的CPU数;第二个参数是集群类型。
注意:在结束集群时使用stopCluster()
下面使用snow包做一个并行运算。
#并行运算K均值聚类
数据是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)]]

##使用clusterApply并行计算

library(snow)
cl <- makeCluster(4, type="SOCK")
ignore <- clusterEvalQ(cl, {library(MASS); NULL}) #用clusterEvalQ函数初始化内核,在每一个内核中载入包
results <- clusterApply(cl, rep(25, 4), function(nstart) kmeans(Boston, 4, nstart=nstart)) #parallel computing
i <- sapply(results, function(result) result$tot.withinss)
result <- results[[which.min(i)]]

相比较clusterEvalQ而言,clusterCall更好用,它的第一个参数为集群对象,第二个参数为一个函数,并且其他的参数可以传递给这个函数。最终返回一个列表。

clusterCall(cl, function() { library(MASS); NULL })

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并行运算
clusterApplyLBclusterApply函数相似,但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)

clusterApplyLB
作为对照,我们用clusterApply函数来观察运行时间

tm1 <- snow.time(clusterApply(cl, sleeptime, Sys.sleep))
plot(tm1)

clusterApply
由此看出clusterApplyLB效率更高。
##使用parLapply并行运算
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)

clusterApply
由图看出并不高效,因为有大量的输入输出时间,下面再试一试clusterApplyLB

tm3 <- snow.time(clusterApplyLB(cl, sleeptime, bigsleep, bigmatrix))
plot(tm3)

clusterApplyLB
由上图看出,运算集中在第1、2和3个内核上,第4个内核上运算的时间非常少,及运算效率差,但总体还是比clusterApply函数要好一些。
看看最终的函数parLapply

tm4 <- snow.time(parLapply(cl, sleeptime, bigsleep, bigmatrix))
plot(tm4)

parLapply
由此看出,传输交换的时间大大缩短了,因此提高了效率。

参考文献 参考文献 参考文献

  1. Luke Tierney, A. J. Rossini, Na Li, H. Sevcikova, package snow.
  2. Q. Ethan McCallum and Stephen Weston, Parallel R.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值