[英]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.