超过R与C++的桥梁:Rcpp
当前位置:以往代写 > 其他教程 >超过R与C++的桥梁:Rcpp
2019-06-14

超过R与C++的桥梁:Rcpp

超过R与C++的桥梁:Rcpp

因为写R扩展的需要,我用Rcpp其实有一阵子了。我一直在强调,把利便和富厚的R情况与系统级语言如C/C++等团结才是适合我现时计较的王道。但R自带的C/C++的API接话柄在是太难用,极端限制人的利用欲望。我试图把它们用最简朴的方法论述过,好比可以看这里和这里。但实际应用中无法因繁就简,照旧制止不了写一大堆反复代码,记一大堆生僻的API。于是Rcpp成了我的救星,出格是前两天进级后,我意外地发明白许多新的特性,固然还没真正利用,但预计会使得我的事情更有效率。把这个包的几篇文档拿来研究了一番,做了些条记。


Rcpp的终极方针,是通过C++面向工具与模板编程的机制,把险些所有R API与数据工具都封装成类以及类的要领。这样,写C++扩展的人只需要相识这些类以及这些类的挪用即可,而把接口界说、垃圾接纳(gc)、异常捕捉、数据范例的转换等等对付R/C++交互都是必需的事情都埋没了起来。新版的Rcpp在效率上更是花了大工夫,一个突出的特点是淘汰了数据工具的拷贝转换,直接对本来的R工具举办操纵,这样无论是时间上照旧空间上,都得到了很大的长处(这些特另外淹灭我在利用旧版Rcpp时深有体会,新版我还没深入利用,不知道会晋升几多)。这里的阐述都是针对新版(今朝是0.9.1)Rcpp的,对比而言,旧版的接口真是浮云。


一个例子: Rcpp与根基的R API在写扩展时的比拟


见下图的两段代码。(a)里的几个你不熟悉的数据范例与函数都是R API界说的范例与函数,个中包罗了R工具的建设、数据范例的转换、内存工具的掩护(防范gc),看起来很别扭,光这些API不知又得淹灭你几多的脑容量。(b)就很简朴了,整个就一正常的c++代码,只是引入了一个Rcpp名空间下的NumericVector类罢了。事实上,Rcpp操作类的担任机制,为险些所有的R根基数据范例都成立了一个类来打点,好比这里的NumericVector类就是打点数值型向量数据范例的。


Rcpp的类条理布局


Rcpp打点R工具的基类叫RObject,正如前面所述,可以通报一个R工具以结构这个类的实例,旧版的处理惩罚会把工具拷贝成一个C++的STL工具,新版则只是简朴地生存了一个对它的引用,类仅充当一个署理的脚色,把所有的操纵都在内部通过R API来完成。RObject还提供了一些工具通用的要领,如工具属性查询要领:isNULL、isObject、isS4;工具属性打点要领:attributeNames, hasAttribute, attr;slots的打点要领:hasSlot, slot。这些要领对付R用户来说应该都很熟悉,就不消去查那艰涩难解的R API函数了。由这个基类派生出来的子类则认真详细工具的特定的处理惩罚,如Vector、Matrix、Character、Environment、Function等工具的子类。差异的数据工具大概有差异的数据范例,所以又有差异的类来处理惩罚,好比Vector就有IntegerVector, NumericVector, RawVector, LogicalVector, CharacterVector, GenericVector(List), ExpressionVector。


R与C++间的数据范例转换


虽说Rcpp只生存R工具的一个引用,但两种差异数据名目间的转换必定也是必需的,所以有了Rcpp::wrap与Rcpp::as函数,前者用于把C++工具转换成R工具,后者则相反。这两个函数都是用C++的模板元编程技能实现的。这些转换有时候是隐式挪用的,如赋值时双方的范例不匹配,就会作出自动转换。


异常捕捉


由于R与C++利用差异的异常捕捉模子,所以要加以处理惩罚,才气在R情况中捕捉到来自C++的异常动静。所以,Rcpp提供了BEGIN_RCPP与END_RCPP这一对宏,只要把有大概呈现C++异常的代码放到这对宏里,就可以在R情况中吸收到C++的异常。


机能较量


Rcpp从头设计的一个重要思路就是使得工具的拷贝只管地少,同时其设计也警惕了STL的设计道理,好比对iterator的利用。固然作者对取值operator[]作了多方的优化,但机能却是不如iterator好。下面的表格是对一个卷积计较多次的计较时间较量。


R API是原生的支持,这里用作参照。可以看到的是旧版的Rcpp实现(最后一行)的机能比原生支持差得甚远,这是因为有过多的工具拷贝与转换的缘故。利用了operator[]的实现机能有了很大的晋升,但照旧比不上原生的支持。但利用了iterator实现的版本,已经跟原生支持的效率差不多了。更神奇的是,第二行名为Rcpp sugar的实现比原生支持更快。这是一个仍在开拓完善中的模块,但今朝已经拥有许多的成果了。这个模块的目标在于在C++里也能充实地操作R的向量化计较的特性,不单代码写起来感受跟R的思路很雷同,效率上也获得了很大的晋升。


正在举办中的开拓


上面已经提到,Rcpp sugar是一个正在开拓完善中的模块,拥有它之后,你可以在C++层面挪用更多的R的函数,利用更多的R的特性。另一个重要的模块是Rcpp modules,它开导自Boost.Python模块,通过这个模块,要把C++函数导入到R变得更为简朴,只要通过Rcpp的宏RCPP_MODULE把一般的C++函数包装一下,就可以直接在R情况中导入并利用,完全不需要特另外转换事情。


Rcpp的作者还在开拓一个名为RcppArmadillo的包,Armadillo是一个模板化的C++线性代数包,试图在效率与易用性上寻求个均衡点,而RcppArmadillo就是一个接口,使得在R中也能利用Armadillo。

    关键字:

在线提交作业