☰
R语言中的并行计算实现
2026/10/5 9:56:38 网站建设 项目流程

文章目录

  • parallel包
  • foreach包
    • 实例
    • 参数介绍
    • 技巧
  • Snowfall包
    • snowfall的一般框架
  • 并行计算的嵌套

并行计算有显性并行和隐式并行,

隐式并行:OpenBLAS,Intel MKL,NVIDIA cuBLAS,H2O(参考我的博客)等

显性并行:parallel(主打lapply应用)、foreach(主打for循环)、SupR、还有利用GPU的办法(gpuR)

介绍可以参考:
https://cosx.org/2016/09/r-and-parallel-computing
https://blog.csdn.net/sinat_26917383/article/details/52719232

parallel是比较基础的,不需要额外安装,直接加载就行,但是不是很稳定,关于parallel包的介绍可以参考:
https://blog.csdn.net/weixin_41929524/article/details/81707053
https://blog.csdn.net/faith_mo_blog/article/details/51646386

parallel包

paralle包的并行主要靠parLapply()、parSapply()、parApply()、parRapply()、parCapply()函数实现

cl<- makeCluster(detectCores()) all.pcg <- c("httr","jsonlite","magrittr") worker.init <- function(p) sapply(p,library,character.only=TRUE) clusterCall(cl, worker.init, all.pcg) #此句用于将各个子进程的环境全部加载分配到各进程环境中 mydata2 <- parLapply( cl, #进程环境 1:16, #遍历参数 GETPDF #测试代码语句 ) %>% rlist::list.rbind() stopCluster(cl)
cl <- makePSOCKcluster(使用核的数量) clusterExport(cl,输入变量) clusterEvalQ(cl, 输入包) x <- parLapply(cl,循环次数,函数) 情形1: myfun <- function(x){ x^2 } 这个函数输入就只有x,则并行可以如下 cl <- makePSOCKcluster(2) #使用两个核 out <- parLapply(cl,1:10,myfun) # 这样1:10直接输入到函数myfun里面,作为x的值 情形2: myfun <- function(x){ x^2 + y + z } 这时候函数里除了x还多出来y和z,先给y和z赋值 y <- 1 z <- 2 通过clusterExport把赋值的变量送进函数里面 cl <- makePSOCKcluster(2) clusterExport(cl,c("y","z")) #传输外部变量 out <- parLapply(cl,1:10,myfun) 情形3: myfun <- function(x){ 某函数(x^2 + y + z) } 这个情形需要用到某函数,该函数包含在某包中。这时候需要通过clusterEvalQ将某包传入 cl <- makePSOCKcluster(2) clusterExport(cl,c("y","z")) clusterEvalQ(cl,c("某包")) x <- parLapply(cl,1:10,myfun) stopCluster(cl) gc()

foreach包

实例

# foreachlibrary(foreach)library(doParallel)#分配核心数,这里获取了物理核心数cores<-detectCores(logical=F)cl<-makeCluster(cores)registerDoParallel(cl,cores=cores)system.time(#.combine是数据的合并方法,如果缺省则返回一个listres<-foreach(i=1:20,.combine='rbind',.packages=c('需要的包'),.export=c('需要的函数和变量'))%dopar%{#主要代码区域for(jin1:100000){s=i+j}return(s)})#关闭并行stopImplicitCluster()stopCluster(cl)

参数介绍

  • %do%: 严格按照顺序执行任务(所以,也就非并行计算),%dopar%并行执行任务,%do%时候就像sapply或lapply,%dopar%就是并行启动器

  • .combine:运算之后结果的显示方式,default是list,“c”返回vector, cbind和rbind返回矩阵,并把数据整合起来.

  • .init:.combine函数的第一个变量

  • .final:返回最后结果

  • .inorder:TRUE则返回和原始输入相同顺序的结果(对结果的顺序要求严格的时候),FALSE返回没有顺序的结果(可以提高运算效率)。这个参数适合于设定对结果顺序没有需求的情况。

  • .muticombine:设定.combine函数的传递参数,default是FALSE表示其参数是2,TRUE可以设定多个参数

  • .maxcombine:设定.combine的最大参数

  • .errorhandling:如果循环中出现错误,对错误的处理方法

  • .packages:指定在%dopar%运算过程中依赖的package(%do%会忽略这个选项),用于并行一些机器学习算法。

  • .export:在编译函数的时候需要预先加载一些内容进去,类似parallel的clusterExport

用法举例:

x<-foreach(ii=1:100,.combine="c",.export=c("semimetric.pca","quadratic"))%dopar%func(ii)

可参考:https://blog.csdn.net/u011178441/article/details/90742330

技巧

如果觉得在foreach()中写太多加载包不美观可以使用clusterExport()函数:

cl<-makeCluster(cores)registerDoParallel(cl)clusterExport(cl,c("semimetric.pca","quadratic"))x<-foreach(ii=1:100,.combine="c")%dopar%func(ii)#关闭并行stopImplicitCluster()stopCluster(cl)

Snowfall包

另外一个比较稳定的并行包是snowfall依赖snow包和parallel包,可以参考:
https://blog.csdn.net/weixin_41929524/article/details/81742322

可以比较一下运行速度:

library(parallel)#用于并行计算library(snowfall)# 载入snowfall包,用于并行计算system.time(for(iin1:2250){for(jin1:100000){s=i+j}})myfun<-function(i){for(jin1:100000){s=i+j}}system.time(# 并行初始化sfInit(parallel=TRUE,cpus=detectCores(logical=F)-1)# 进行lapply的并行操作s<-sfLapply(1:2250,myfun)# 结束并行,返还内存等资源sfStop())

snowfall的一般框架

library((parallel)) library(snowfall) #初始化计算群 sfInit(parallel = TRUE, cpus = min(coresmax,detectCores(logical = T))) sfExport(XXX)#为每个进程载入相关的函数,数据 sfLibrary(XXX)#为每个进程载入相关的包 parlresult<-sfLapply(1:100, fun) sfStop() #结束并行

并行计算的嵌套

对于第一级并行化,必须使用分布式内存技术(如 snow 包中的 makeCluster()),而在第二级并行化中,必须使用共享内存技术(多核包,mclapply())。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询