已经大半年没有更新博客了。。最近都跑去写分析报告半年没有r
这次记录下关于r循环(百万级以上)死慢死慢的问题,这个问题去年就碰到过,当时也尝试过多线程,but failed……昨天试了下,终于跑通了,而且过程还挺顺利
先查下自己电脑几核的,n核貌似应该选跑n个线程,线程不是越多越好,线程个数和任务运行时间是条开口向下的抛物线,最高点预计在电脑的核数上。
detectcores( )检查当前电脑可用核数 我的是4所以step2选的是4
library(parallel)cl.cores <- detectcores()
多线程计算
twd("c:\\urs\\siyuanmao\\documents\\imdada\twd("c:\\urs\\siyuanmao\\documents\\imdada\\0-渠道投放和新人券联动模型\\测算")options(scipen=3) ##取消科学计数法channel_ad_ios_data<-q(0,50000,5000)channel_ad_android_data<-q(0,100000,10000)library(parallel)func <- function(n){#n=1result_data<-read.csv("发券方案.csv",stringsasfactors=fal)total_coupon_solution_data<-read.csv("结果表框架.csv",stringsasfactors=fal)coupon_solution_data<-subt(result_data,solution== paste('方案',n,p=""))for (i in 1:11){#i=3coupon_solution_data$channel_ad_cost[3]<-5000*(i-1)for (j in 1:11){#j=5coupon_solution_data$channel_ad_cost[4]<-10000*(j-1)solution_mark<-paste('方案',n,i,j,p="-")coupon_solution_data$solution<-solution_marktotal_coupon_solution_data<-rbind(total_coupon_solution_data,coupon_solution_data)}}print(solution_mark)return(total生活常识全知道_coupon_solution_data)}#func(10)system.time({x <- 1:7776cl <- makecluster(4) # 初始化四核心集群results <- parlapply(cl,x,func) # lapply的并行版本res.df <- do.call('rbind',results) # 整合结果stopcluster(cl) # 关闭集群})df=as.data.frame(res.df)-渠道投放和新人券联动模型\\测算")options(scipen=3) ##取消科学计数法channel_ad_ios_data<-q(0,50000,5000)channel_ad_android_data<-q(0,100000,10000)library(parallel)func <- function(n){#n=1 result_data<-read.csv("发券方案.csv",stringsasfactors=fal) total_coupon_solution_data<-read.csv("结果表框架.csv",stringsasfactors=fal) coupon_solution_data<-subt(result_data,solution== paste('方案',n,p="")) for (i in 1:11){#i=3 coupon_solution_data$channel_ad_cost[3]<-5000*(i-1) for (j in 1:11){#j=5 coupon_solution_data$channel_ad_cost[4]<-10000*(j-1) solution_mark<-paste('方案',n,i,j,p="-") coupon_solut科技园中英文学校ion_data$solution<-solution_mark total_coupon_solution_data<-rbind(total_coupon_solution_梅花的品质data,coupon_solution_data) } } print(solution_mark) return(total_coupon_solution_data)}#func(10)system.time({x <- 1:7776cl <- makecluster(4) # 初始化四核心集群results <- parlapply(cl,x,func) # lapply的并行版本res.df <- do.call('rbind',results) # 整合结果stopcluster(cl) # 关闭集群})df=as.data.frame(res.df)
原来非多线程的时候,我预计要跑12个小时以上,电脑发出呼呼~~的响声,查了下python循环会快点,然后改为python版(已经很久没有用了,连个range都不会写,摸索了大半天才改好,但是速度还是慢==),于是改成多线程,运行25分钟就出结果了~~
补充:r语言 多线程
install.packages("parallel")library(parallel)
detectcores() 检查当前的可用核数
clusterexport() 配置当前环境
makecluster() 分配核数
stopcluster() 关闭集群
parlapply() lapply()函数的并行版本
其实r语言本来就是一门向量化语言,如果是对于一个向量的操作,使用apply函数一族能获得比较高的效率,相比于for循环,这种高效来自于:
用c实现了for循环
减少对于data.frame等数据结构等不必要的拷贝
但是很多时候,如果想更快的话,光apply函数一族还不足够,这时候就能用上多线程。
r语言parallel包可以帮助实现多线程。
cl.cores <- detectcores()#结果> cl.cores[1] 8
cl <- makecluster(4) # 初始化四核心集群###并行任务stopcluster(cl) # 关闭集群
#定义计算平方函数square <- function(x){ return(x^2)}
#利用并行计算计算平方函数num <- c(1:3)cl <- makecluster(4) # 初始化四核心集群results <- parlapply(cl,num,square)#调用parlapply并行计算平方函数final <- do.call('c',results)#整合结果stopcluster(cl) # 关闭集群#结果> final[1] 1,4,9
思考:在如此小的计算方式下,开4个核计算是否比开一个核要快
答案:当然是不一定,因为涉及到调度方式等额外开销,所以不一定快,因为真正并行起作用的地方在于大数据量的计算。
两段对比代码
#定义计算平方函数square <- function(x){ ######### #一段冗余代码增加执行时间 y = 2*x if(y <300) {z = y} el {z = x} ########## return(x^2)}num <- c(1:10000000)
#并行计算print(system.time({ cl <- makecluster(4) # 初始化四核心集群 results <- parlapply(cl,num,square)#调用parlapply并行计算平方函数final <- do.call('c',results)#整合结果stopcluster(cl) # 关闭集群}))#结果用户 系统 流逝 7.89 0.27 19.01
#普通计算print(system.time({ results <- lapply(num,square) final <- do.call('c',results)#整合结果}))#结果用户 系统 流逝 29.74 0.00 29.79
显然在数据量比较大的时候,并行计算的时间几乎就是于核数反比。不过,也不是多开几个核就好,注意内存很容易超支的,每个核都分配相应的内存,所以要注意内存开销。出现内存问题的时候,需要检查是否代码是否合理,r语言版本(64位会比32位分配的内存大),核分配是否合理。
r语言里边对于环境变量有着有趣的定义,一层套一层,这里不做深入展开。
类似于在c语言函数中使用全局变量,r在执行并行计算的时候,如果需要计算的函数出现在全局(上一级),那么就需要声明引入这个变量,否则将会报错。
#定义计算幂函数ba = 2square <- function(x){ return(x^ba)}num <- c(1:1000000)
#利用并行计算计算幂函数cl <- makecluster(4) # 初始化四核心集群results <- parlapply(cl,num,square)#调用parlapply并行计算平方函数final <- do.call('c',results)#整合结果stopcluster(cl) # 关闭集群#结果报错error in checkforremoteerrors(val) : 4 nodes produced errors; first error: 找不到对象'ba'
#利用并行计算计算幂函数cl <- makecluster(4) # 初始化四核心集群clusterexport(cl,"ba",envir = environment())results <- parlapply(cl,num,square)#调用parlapply并行计算平方函数final <- do.call('c',results)#整合结果stopcluster(cl) # 关闭集群#结果> final[1] 1,4,9,16,25.......
除了parallel包以外,还有针对并行for循环的foreach包未来的世界作文,foreach()的使用也与parlapply()类似,两个功能也类似,其中遇到的问题也类似。
install.packages("foreach")library(parallel)
#定义计算幂函数square <- function(x){ return(x^2)}
非并行情况的使用:
参数中的combine就是整合结果的函数,可以是c,可以是rbind,也可以是+等
results = foreach(x = c(1:3),.combine = 'c') %do% square(x)#结果> results[1] 1,4,9
并行情况的使用:
注意并行情况的时候,需要与parallel包进行配合,引入library(d艺术生考研oparallel)。同时%do%需要改成%dopar%。另外与parallel包不一样的是,需要多加一句registerdoparallel(cl)来注册核进行使用。
cl <- makecluster(4)registerdoparallel(cl)results = foreach(x = c(1:100000),.combine = 'c') %dopar% square(x)stopcluster(cl)
同parallel包并行计算前需要clusterexport()来引入全局变量一样,foreach也同样需要声明,不同的是,foreach声明方式直接写在foreach()的参数export里边。
#定义计算幂函数ba = 2square <- function(x){ return(x^ba)}cl <- makecluster(4)registerdoparallel(cl)results = foreach(x = c(1:100000),.combine = 'c',.export ='ba' ) %dopar% square(x)stopcluster(cl)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。如有错误或未考虑完全的地方,望不吝赐教。
本文发布于:2023-04-09 03:01:26,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/a9e9a0fc23f636be921b0e052ff908ef.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:R语言多线程运算操作(解决R循环慢的问题).doc
本文 PDF 下载地址:R语言多线程运算操作(解决R循环慢的问题).pdf
留言与评论(共有 0 条评论) |