[英]Convert RcppArmadillo vector to Rcpp vector
我正在尝试将 RcppArmadillo 向量(例如arma::colvec
)转换为 Rcpp 向量( NumericVector
)。 我知道我可以先将arma::colvec
转换为SEXP
,然后将SEXP
转换为NumericVector
(例如as<NumericVector>(wrap(temp)
),假设 temp 是一个arma::colvec
对象)。 但是这样做的好方法是什么?
我想这样做只是因为我不确定是否可以将arma::colvec
对象作为参数传递给Rcpp::Function
对象。
我试图用参数arma::vec
评估一个Rcpp::Function
,它似乎采用四种形式的参数而没有编译错误。 也就是说,如果f
是一个Rcpp::Function
而a
是一个arma::vec
,那么
f(a)
f(wrap(a))
f(as<NumericVector>(wrap(a)))
f(NumericVector(a.begin(),a.end()))
不会产生编译和运行时错误,至少表面上看是这样。
为此,我对四种说法进行了小测试。 因为我怀疑垃圾回收会出问题,所以我再次测试它们gctorture
。
gctorture(on=FALSE)
Rcpp::sourceCpp(code = '
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double foo1(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(a, b));
}
return sum;
}
// [[Rcpp::export]]
double foo2(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(wrap(a),wrap(b)));
}
return sum;
}
// [[Rcpp::export]]
double foo3(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(as<NumericVector>(wrap(a)),as<NumericVector>(wrap(b))));
}
return sum;
}
// [[Rcpp::export]]
double foo4(arma::vec a, arma::vec b, Function f){
double sum = 0.0;
for(int i=0;i<100;i++){
sum += as<double>(f(NumericVector(a.begin(),a.end()),NumericVector(b.begin(),b.end())));
}
return sum;
}
')
# note that when gctorture is on, the program will be very slow as it
# tries to perfrom GC for every allocation.
# gctorture(on=TRUE)
f = function(x,y) {
mean(x) + mean(y)
}
# all three functions should return 700
foo1(c(1,2,3), c(4,5,6), f) # error
foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
foo3(c(1,2,3), c(4,5,6), f) # correct answer
foo4(c(1,2,3), c(4,5,6), f) # correct answer
结果,第一种方法产生错误,第二种方法产生错误答案,只有第三种和第四种方法返回正确答案。
> # they should return 700
> foo1(c(1,2,3), c(4,5,6), f) # error
Error: invalid multibyte string at '<80><a1><e2>'
> foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
[1] 712
> foo3(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
> foo4(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
请注意,如果gctorture
设置为FALSE
,则所有函数都将返回正确的结果。
> foo1(c(1,2,3), c(4,5,6), f) # error
[1] 700
> foo2(c(1,2,3), c(4,5,6), f) # wrong answer (occasionally)!
[1] 700
> foo3(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
> foo4(c(1,2,3), c(4,5,6), f) # correct answer
[1] 700
这意味着方法 1 和方法 2 在运行时收集垃圾时会受到中断,我们不知道它何时发生。 因此,不正确包装参数是危险的。
编辑:截至 2017 年 12 月 5 日,所有四个转换都产生了正确的结果。
f(a)
f(wrap(a))
f(as<NumericVector>(wrap(a)))
f(NumericVector(a.begin(),a.end()))
这是基准
> microbenchmark(foo1(c(1,2,3), c(4,5,6), f), foo2(c(1,2,3), c(4,5,6), f), foo
3(c(1,2,3), c(4,5,6), f), foo4(c(1,2,3), c(4,5,6), f))
Unit: milliseconds
expr min lq mean median uq
foo1(c(1, 2, 3), c(4, 5, 6), f) 2.575459 2.694297 2.905398 2.734009 2.921552
foo2(c(1, 2, 3), c(4, 5, 6), f) 2.574565 2.677380 2.880511 2.731615 2.847573
foo3(c(1, 2, 3), c(4, 5, 6), f) 2.582574 2.701779 2.862598 2.753256 2.875745
foo4(c(1, 2, 3), c(4, 5, 6), f) 2.378309 2.469361 2.675188 2.538140 2.695720
max neval
4.186352 100
5.336418 100
4.611379 100
3.734019 100
f(NumericVector(a.begin(),a.end()))
比其他方法快一点。
这应该适用于arma::vec
、 arma::rowvec
和arma::colvec
:
template <typename T>
Rcpp::NumericVector arma2vec(const T& x) {
return Rcpp::NumericVector(x.begin(), x.end());
}
我有同样的问题。 我用wrap在几层for循环的核心做转换,速度很慢。 我认为包装功能是拖慢速度的罪魁祸首,所以我想知道是否有一种优雅的方法可以做到这一点。
至于雷蒙德的问题,您可能想尝试包括像这样的命名空间: Rcpp::as<Rcpp::NumericVector>(wrap(A))
而不是或包括一行using namespace Rcpp;
在代码的开头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.