是否有任何理由为什么我应该更喜欢Rcpp::NumericVector
过std::vector
?
例如,下面的两个功能
// [[Rcpp::export]] Rcpp::NumericVector foo(const Rcpp::NumericVector& x) { Rcpp::NumericVector tmp(x.length()); for (int i = 0; i < x.length(); i++) tmp[i] = x[i] + 1.0; return tmp; } // [[Rcpp::export]] std::vectorbar(const std::vector & x) { std::vector tmp(x.size()); for (int i = 0; i < x.size(); i++) tmp[i] = x[i] + 1.0; return tmp; }
在考虑其工作和基准性能时是等效的.我知道Rcpp提供了糖和矢量化操作,但是如果只是将R的向量作为输入并将向量作为输出返回,那么我使用哪一个会有什么区别吗?std::vector
在与R交互时可以使用导致任何可能的问题吗?
在考虑其工作和基准性能时是等效的.
我怀疑基准测试是否准确,因为从a SEXP
到std::vector
需要从一个数据结构到另一个数据结构的深层复制.(当我打字时,@ DirkEddelbuettel运行了一个微基准测试.)
Rcpp对象的标记(例如const Rcpp::NumericVector& x
)只是视觉糖.默认情况下,给定的对象是指针,因此很容易产生波纹修改效果(见下文).因此,没有与const std::vector
有效"锁定"和"传递引用" 存在的真实匹配.
std::vector
在与R交互时可以使用导致任何可能的问题吗?
简而言之,没有.支付的唯一惩罚是对象之间的转移.
这种转移的好处是修改NumericVector
分配给另一个转移的值NumericVector
不会导致多米诺骨牌更新.实质上,每个std::vector
都是另一个的直接副本.因此,以下情况不可能发生:
#include// [[Rcpp::export]] void test_copy(){ NumericVector A = NumericVector::create(1, 2, 3); NumericVector B = A; Rcout << "Before: " << std::endl << "A: " << A << std::endl << "B: " << B << std::endl; A[1] = 5; // 2 -> 5 Rcout << "After: " << std::endl << "A: " << A << std::endl << "B: " << B << std::endl; }
得到:
test_copy() # Before: # A: 1 2 3 # B: 1 2 3 # After: # A: 1 5 3 # B: 1 5 3
是否有任何理由为什么我应该更喜欢
Rcpp::NumericVector
过std::vector
?
有几个原因:
如前所述,使用Rcpp::NumericVector
避免了C++的深层复制. std::vector
您可以访问糖功能.
能够在C++中 "标记" Rcpp对象(例如,通过添加属性).attr()
"如果不确定,只需要时间."
只需将这几行添加到您已有的文件中:
/*** R library(microbenchmark) x <- 1.0* 1:1e7 # make sure it is numeric microbenchmark(foo(x), bar(x), times=100L) */
然后只是调用sourceCpp("...yourfile...")
生成以下结果(加上有符号/无符号比较的警告):
R> library(microbenchmark) R> x <- 1.0* 1:1e7 # make sure it is numeric R> microbenchmark(foo(x), bar(x), times=100L) Unit: milliseconds expr min lq mean median uq max neval cld foo(x) 31.6496 31.7396 32.3967 31.7806 31.9186 54.3499 100 a bar(x) 50.9229 51.0602 53.5471 51.1811 51.5200 147.4450 100 b R>
您的bar()
解决方案需要制作副本以在R内存池中创建R对象.foo()
才不是.这对于你经常运行多次的大型向量很重要.在这里,我们看到收盘率约为1.8.
在实践中,如果您喜欢一种编码风格而不是另一种编码风格,则可能无关紧要.