第1章 R语言中的并行处理入门
标准:时间,开发,运行,工具,R机器,多核。
rdsm,openmp,conda。
相互网页外链。
第一章
1.1 反复出现的主题: 良好并行所具有的标准
R(解释性语言)的核心操作都在语言内部进行了高效的实现,因而只要正确使用,R语言一般能够提供较好的性能
1.1.1 足够快(良好并行的标准?)
1.1.2 “R+X”
1.2 关于机器
多核系统,集群(几十个结点),GPU
1.3 反复出现的主题: 不要把鸡蛋放在一个篮子里(跨平台)
可以使用多种硬件、也能被多种编程语言调用的软件包对用户有着巨大的吸引力。
第7章和一些后面小节将要讨论的Thrust,就是这
种现象的缩影。同样的Thrust代码,既能在多核平台上运行,也能在GPU
平台上运行,并且由于它是基于C++的,它能被R和其他大部分语言调用。
长话短说,Thrust 使得我们在开发并行代码的时候能够“两面下注”
消息传递软件系统,比如R的snow、Rmpi和pbdR扩展包,也有基
本相同的优势,因为它们既能在多核机器上运行,也能在集群上运行。
1.4 扩展示例: 相互网页外链
1.4.1 串行代码
mutoutser<- function(links) {
nr <- nrow(links)
nc <- ncol(links)
tot = 0
for (i in 1:(nr-1)) {
for (j in (i+1):nr) {
for (k in 1:nc)
tot <- tot + links[i,k] * links[j,k]
}
}
tot / (nr*(nr-1)/2)
}
# 生成一个指定大小(nr 行,nc 列)的二进制矩阵 lnk,然后调用 mutoutser 函数计算
sim <- function(nr,nc) {
lnk <- matrix(sample(0:1,(nr*nc),replace=TRUE),nrow=nr)
print(system.time(mutoutser(lnk)))
}
sim(500,500)
mutoutser1<- function(links) {
nr <- nrow(links)
nc <- ncol(links)
tot <- 0
for (i in 1:(nr-1)) {
tmp <- links[(i+1):nr,] %*% links[i,]
tot <- tot + sum(tmp)
}
tot / (nr*(nr-1)/2)
}
sim1<- function(nr,nc) {
lnk <- matrix(sample(0:1,(nr*nc),replace=TRUE),nrow=nr)
print(system.time(mutoutser1(lnk)))
}
sim1(500,500)
sim1(2000,2000)
1.4.2 并行工具的选择snow 包
1.4.4 snow包的简介
先来总结一下 snow 包的操作:
使用了 scatter/gather范式:我们同时有多个R的实例在运行,它们可
能在集群中的好几个机器上,也有可能在一个多核机器上,我们把其中的一个实例称为manáger,其他的称为worker。并行计算将如下进行:
1.4.5 并行代码
library(parallel)
#该函数接收一个索引块(ichunk),使用参数lnks(全局变量,后面定义),计算矩阵的乘积并累加结果。
# 主要负责在并行计算中处理一部分数据的计算。
doichunk <- function(ichunk) {
tot <- 0
nr <- nrow(lnks)
for (i in ichunk) {
tmp <- lnks[(i+1):nr,] %*% lnks[i,]
tot <- tot + sum(tmp)
}
return(tot)
}
# 1.该函数接收一个集群对象cls,将全局变量lnks导出到集群中。
# 2.将数据划分成多个块,给每个工作节点分配任务,并使用doichunk处理。
# 3.最后,计算所有工作节点的结果总和并取平均。
# ichunks[] cls[]
mutoutpar <- function(cls) {
nr <- nrow(lnks) # lnks global
clusterExport(cls,"lnks") # 将links导出到cluster中
ichunks <- clusterSplit(cls,1:(nr-1)) # ichunks是索引块的列表
tots <- clusterApply(cls,ichunks,doichunk) # tots是每个工作节点的结果列表
Reduce(sum,tots) / nr # 收集worker的结果并求平均
}
# 该函数用于生成一个大小为nr * nc的随机二进制矩阵lnks。
# 调用mutoutpar进行并行计算,并记录计算时间。
snowsim <- function(nr,nc,cls) {
lnks <<- matrix(sample(0:1,(nr*nc),replace=TRUE),nrow=nr)
print(system.time(mutoutpar(cls)))
}
# init本地多核机器集群
initmc <- function(nworkers) {
makeCluster(nworkers) # return cluster object
}
#1.首先创建一个具有2个工作节点的集群并执行snowsim进行矩阵操作
#2.再次创建一个具有4个工作节点的集群并执行同样操作。
cluser=initmc(2)
snowsim(2000,2000,cluser)
system.time(mutoutser1(lnks)) # 之前的计算函数
cluser <-initmc(4)
snowsim(2000,2000,cluser)
system.time(mutoutser1(lnks))