如何加速R?

在挖了n个R的坑之后,我还是决定把自己遇到的坑都写一下,免得自己又重复掉进相同的坑里。关于R语言加速的问题,《Advanced R》里面的一句让我印象深刻:

Optimising code to make it run faster is an iterative process:  
1. Find the biggest bottleneck (the slowest part of your code).  
2. Try to eliminate it (you may not succeed but that`s ok).  
3. Repeat until your code is “fast enough.”  
This sounds easy, but its not.  

Even experienced programmers have a hard time identifying bottlenecks in their code. Instead of relying on your intuition, you should profile your code: use realistic inputs and measure the run-time of each individual operation.

所以,如果你想优化的你的R代码,直觉大多数时候都不起作用。你需要一步一步的测试一点点的改进,并且把你改进的经验记录下来

一. 优化R代码的方向

关于R的进阶教程比较著名的包括:《The art of R programming》、《Advanced R》、《The R inferno》三本书难度由浅到深,分别从R语言常用的数据结构和操作,到R泛化函数,到最后如何从细节,习惯甚至思想上改进你的代码,都给出了非常漂亮的例子。我也在一直不停的啃书当中。。。

总的来说,加速R代码可以从三个方面入手:

  1. R代码本身出发进行优化

  2. 利用并行运算

  3. 利用Rcpp和其他的运算库

对于这三个方向,我会持续的把自己遇见的问题记录在这里。这里强烈推荐用microbenchmark这个包对代码的运行时长进行测试。

二. 加速方法说明

1. 从R代码出发

关于这一块,上面三本书,尤其是《The R inferno》已经介绍的非常详细了。我这里仅仅举几个常用的例子。

(1)尽量不使用中间变量,使用嵌套函数,或者直接返回表达式。这样避免了分配内存的时间。

640?wx_fmt=png


(2)向量化你的代码,避免单独操作。这个很好理解,批量操作总再取出来在放回去的快。当然,pply的函数组也是向量化操作的体现。

640?wx_fmt=png


(3)尽量使用已有的函数,因为这些函数已经包裹好了,甚至调用了专门用来计算的库。(当然这样需要你不停的多看多写)

640?wx_fmt=png

(4)尽量不使用循环,而使用pply组,replicate等函数。这些函数对你的操作进行包裹,从而提高运行速度。

2. 利用并行运算

我对R语言并行计算还只是浅薄的了解。关于并行运算,《Advanced R》里面只有微乎其微的讲解,对于那些真正真正深入的人来说远远不够。这里可以用《Parallel R》《Parallel Computing for Data Science》,这两本书进行学习实战。

R常用的并行计算的库有很多,例如:snow,parallel,multicore等等。当然有的对windows不是特别的友善。这些并行大抵都遵循这样的思路:

  1. 创建一个集群

  2. 把函数分割开来放入集群

  3. 以某种方式合并结果

  4. 关闭你的集群

因为我这里知之甚少,所以从《Parallel R》copy一个例子,来让大家体会。链接:

https://link.zhihu.com/target=http%3A//detritus.fundacioace.com/pub/books/Oreilly.Parallel.R.Oct.2011.pdf

640?wx_fmt=png

下面的图是执行所用的时间的分布。

640?wx_fmt=jpeg

3. 利用Rcpp和其他的运算库

Rcpp是提升R速度的强有力的工具。关于Rcpp的经典教材主要有:《Writing R Extensions》、《Seamless R and C++ Integration with Rcpp》前面本算是个说明文档,后面这一本是在前面的基础上整理成的书,两个都可以看一下。

先给一个计算fibonacci函数的例子。

首先要写一个名字为fibonacci.cpp的函数,可以把如下的代码粘进去:

640?wx_fmt=png

然后我们在R语言里面同样的写一个fibonacci的函数,同时调用进行对比:

640?wx_fmt=png


上面可以看出来Rcpp快了很多。

有些时候,Rcpp不一定就R快。R本身的许多函数是用c包装好的,并且经过核心团队的优化,个人写出的函数很难超越。

在针对不同的使用情况当中,你也可以借助一些其他的工具。关于线性代数的计算,就有很多方便的工具。例如:RcppArmadillo是R团队开发的一个C++的线性代数计算库,具有非常快的运算速度。当然,你也可以借助blasmkl等等,这些都可以大大加速矩阵的计算。

下面给一个矩阵乘法的例子,来看看:Rcpp,blas,R,RcppArmadillo哪个更快。这个例子的来源是Stack Overflow

RcppArmadillo

640?wx_fmt=png


Rcpp

640?wx_fmt=png


BLAS

640?wx_fmt=png


比较

640?wx_fmt=png


虽然,blas在计算上已经非常强大,RcppArmadillo竟然表现的还要好。对于广大使用Rcpp的群众来说,RcppArmadillo无疑是一个强有力的矩阵计算工具了。


640?wx_fmt=jpeg

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值