[英]Should I prefer Rcpp::NumericVector over std::vector?
有什么理由我更喜欢Rcpp::NumericVector
不是std::vector<double>
?
例如,下面的两个功能
// [[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::vector<double> bar(const std::vector<double>& x) {
std::vector<double> tmp(x.size());
for (int i = 0; i < x.size(); i++)
tmp[i] = x[i] + 1.0;
return tmp;
}
在考虑其工作和基准性能时是等效的。 我知道Rcpp提供了糖和矢量化操作,但是如果只是将R的向量作为输入并将向量作为输出返回,那么我使用哪一个会有什么区别吗? 在与R交互时,使用std::vector<double>
会导致任何可能出现的问题吗?
在考虑其工作和基准性能时是等效的。
SEXP
到std::vector<double>
需要从一个数据结构到另一个数据结构的深层复制。 (当我打字时,@ DirkEddelbuettel运行了一个微基准测试。) const Rcpp::NumericVector& x
)只是视觉糖。 默认情况下,给定的对象是指针,因此很容易产生波纹修改效果(见下文)。 因此, const std::vector<double>& x
不存在真正的匹配,它们有效地“锁定”和“传递引用”。 在与R交互时,使用
std::vector<double>
会导致任何可能出现的问题吗?
简而言之,没有。 支付的唯一惩罚是对象之间的转移。
这种转移的好处是修改分配给另一个NumericVector
的NumericVector
的值不会导致多米诺骨牌更新。 实质上,每个std::vector<T>
都是另一个的直接副本。 因此,以下情况不可能发生:
#include<Rcpp.h>
// [[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<double>
?
有几个原因:
Rcpp::NumericVector
避免了C ++ std::vector<T>
的深层复制。 .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。
在实践中,如果您喜欢一种编码风格而不是另一种编码风格,则可能无关紧要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.