我和师弟,关于我的程序讨论了一个晚上,程序不长也不短,差不多400行吧(当然也包括多条注释,嘿嘿),我们达成一个共识,程序没错,但就找不出运算缓慢的原因。当天晚上,回宿舍,又开始狂逛论坛,结果很明显,还是一无所获。不知道是什么原因,凌晨干活异常清醒,我经常在这个时候想到比较好的解决方法,当然在一些大牛看来有些笨啦。于是我就利用system.time()函数一条一条测试程序运行时间,突然间发现apply函数即是原因所在,它就像绝大多数外围女,外观美丽,肚子里装的全是水(当然草也是备选啦,任凭你怎么想了),运算速度确实不敢恭维,特别是在我的数值优化中,一次迭代就要花去我两次上厕所的时间,没有夸张,事实就是如此。当时,我很快想到爱恨交织的for循环,没想到,她却我给我一个大大惊喜,速度能甩apply函数几条大街。哇咔咔,安心睡大觉啦!
高兴归高兴,但是我还是不想让她抛头露面,呵呵,躺在床上想了想。于是,今早,师兄答辩之时(当然是干完我的分内之事啦),又开始在论坛狂轰乱炸,这次结果显而易见,idea有了。colSums、colMeans、rowSums和rowMeans函数。为什么是这些函数了?论坛一些大牛指出这些函数是通过底层语言、c++和fortran编写的,运算速度较快,而apply函数是通过R自身的for循环构建的,对数值运算速度提升没啥帮助。很遗憾,本科我只学过VB和SAS,对底层语言一无所知,记忆中大二暑期帮同学借过一本C++,结果超期,罚了我30元,六顿盐水鸭的钱啊。言归正传,接下来说说我对col*,row*函数的运算时间测试,结果验证了大牛们的结论,她确实是最棒滴,此时我如释重负,终于找到一条最优路径,到达罗马城了。
今天废话太多了,不多说了,直接上程序,让大家品味下!对了,关于col*,row*函数的介绍,我写了一个比较粗糙的帖子,大家如果不介意,可以小逛下。链接地址:https://bbs.pinggu.org/thread-3071374-1-1.html
- > #首先生成一个2x15x6x100x100数组
- > x<-array(1:(1800000),c(2,15,6,100,100))
- > #利用三种方法,对该数组第一维度求和
- > #for循环
- > system.time({y<-0;for(i in 1:2) y<-y+x[i,,,,]})
- 用户 系统 流逝
- 0.10 0.00 0.09
- > #apply函数
- > system.time(y1<-apply(x,c(2,3,4,5),sum))
- 用户 系统 流逝
- 7.42 0.00 7.70
- > #colSums函数
- > system.time(y2<-colSums(x,dims=1))
- 用户 系统 流逝
- 0 0 0
- > #验证y、y1、y2是否相等
- > all.equal(y,y1)
- [1] TRUE
- > all.equal(y,y2)
- [1] TRUE
哈哈,看到row*,col*函数威力了吗?显而易见吧,希望此帖能给大家编程,带来速度的大幅度提升(这里就不打火箭了)。呵呵,毕竟在论坛上折腾了几个星期了,不提升也不行哈!
接下来,我会写一个关于加速R矩阵运算的帖子,OpenBLAS,到时欢迎大家关注,一起交流学习。