Rcpp列表操作
注意:此帖子已根据初步反馈进行了编辑
Rcpp和列表操作 - 这是一个热门话题。当对象很大时,复制vs列表中对象的浅拷贝真的很重要。我用下面的一个例子来说明这一点。
问题
加快访问嵌套循环元素的其他想法吗?
设置
首先,让我介绍一下数据结构:嵌套列表,其中内部列表包含向量和矩阵。一个嵌套列表将填充包含小矢量/矩阵的列表,另一个列表包含大的矢量/矩阵。这种结构与许多层次模型一致,其中某些计算是在 i 级别为每个 i 完成的。
outerlistsize=100
vectorsize=1000
outerlist_smalldata=list()
for(ll in 1:outerlistsize){
outerlist_smalldata[[ll]]=list()
outerlist_smalldata[[ll]]$a=rnorm(vectorsize)
outerlist_smalldata[[ll]]$b=matrix(rnorm(vectorsize*4),vectorsize,4)
}
vectorsize=100000
outerlist_bigdata=list()
for(ll in 1:outerlistsize){
outerlist_bigdata[[ll]]=list()
outerlist_bigdata[[ll]]$a=rnorm(vectorsize)
outerlist_bigdata[[ll]]$b=matrix(rnorm(vectorsize*4),vectorsize,4)
}
假设我们想为每个列表做一个简单的矩阵乘法。 R版本很简单:
rfun=function(outerlist){
outerlistsize=length(outerlist)
outmatrix=matrix(NA,outerlistsize,4)
for(ll in 1:outerlistsize){
outmatrix[ll,]= outerlist[[ll]]$a %*% outerlist[[ll]]$b
}
}
现在让我们在Rcpp中做。不同版本:
犰狳
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::depends("RcppArmadillo")]]
// [[Rcpp::export]]
vec cf_copy_i(Rcpp::List inlist){
vec avec = Rcpp::as<arma::vec>(inlist["a"]);
mat bmat = Rcpp::as<arma::mat>(inlist["b"]);
return( vectorise(trans(trans(avec) * bmat)));
}
// [[Rcpp::export]]
mat cf_copy(Rcpp::List outerlist){
int outerlistsize =outerlist.size();
mat outmatrix(outerlistsize,4);
for(int ll=0; ll<outerlistsize; ll++){
Rcpp::List innerlist = outerlist[ll];
outmatrix.row(ll)= trans(cf_copy_i(innerlist));
}
return(outmatrix);
}
浅拷贝
// [[Rcpp::export]]
vec cf_shallow_i(const Rcpp::List & inlist){
NumericVector ave = inlist["a"];
NumericMatrix bma = inlist["b"];
arma::vec avec(ave.begin(), ave.size(), false);
arma::mat bmat(bma.begin(), bma.rows(), bma.cols(), false);
return( vectorise(trans(trans(avec) * bmat)));
}
// [[Rcpp::export]]
mat cf_shallow(const Rcpp::List & outerlist){
int outerlistsize =outerlist.size();
mat outmatrix(outerlistsize,4);
for(int ll=0; ll<outerlistsize; ll++){
Rcpp::List innerlist = outerlist[ll];
outmatrix.row(ll)= trans(cf_shallow_i(innerlist));
}
return(outmatrix);
}
浅拷贝固定暗淡
// [[Rcpp::export]]
vec cf_shallowstrict_i(const Rcpp::List & inlist){
NumericVector ave = inlist["a"];
NumericMatrix bma = inlist["b"];
arma::vec avec(ave.begin(), ave.size(), false, true);
arma::mat bmat(bma.begin(), bma.rows(), bma.cols(), false, true);
return( vectorise(trans(trans(avec) * bmat)));
}
// [[Rcpp::export]]
mat cf_shallowstrict(const Rcpp::List & outerlist){
int outerlistsize =outerlist.size();
mat outmatrix(outerlistsize,4);
for(int ll=0; ll<outerlistsize; ll++){
Rcpp::List innerlist = outerlist[ll];
outmatrix.row(ll)= trans(cf_shallowstrict_i(innerlist));
}
return(outmatrix);
}
STRUCT
// [[Rcpp::export]]
vec cf_nolist_i(const vec & avec, const mat & bmat){
vec outvec= vectorise(trans(trans(avec) * bmat));
return(outvec);
}
struct stuff{
vec a;
mat b;
};
// [[Rcpp::export]]
mat cf_struct(const Rcpp::List & outerlist){
int outerlistsize =outerlist.size();
std::vector<stuff> list_vector;
stuff listi_struct;
List listi;
for(int ij=0; ij<outerlistsize; ij++){
listi = outerlist[ij];
listi_struct.a = as<vec>(listi["a"]);
listi_struct.b = as<mat>(listi["b"]);
list_vector.push_back(listi_struct);
}
mat outmatrix(outerlistsize,4);
for(int ll=0; ll<outerlistsize; ll++){
outmatrix.row(ll)= trans(cf_nolist_i(list_vector[ll].a, list_vector[ll].b));
}
return(outmatrix);
}
结构浅
// [[Rcpp::export]]
mat cf_structshallow(const Rcpp::List & outerlist){
int outerlistsize =outerlist.size();
std::vector<stuff> list_vector;
stuff listi_struct;
List listi;
for(int ij=0; ij<outerlistsize; ij++){
listi = outerlist[ij];
NumericVector ave = listi["a"];
NumericMatrix bma = listi["b"];
arma::vec avec(ave.begin(), ave.size(), false, true);
arma::mat bmat(bma.begin(), bma.rows(), bma.cols(), false, true);
listi_struct.a = avec;
listi_struct.b = bmat;
list_vector.push_back(listi_struct);
}
mat outmatrix(outerlistsize,4);
for(int ll=0; ll<outerlistsize; ll++){
outmatrix.row(ll)= trans(cf_nolist_i(list_vector[ll].a, list_vector[ll].b));
}
return(outmatrix);
}
小数据......
library(rbenchmark)
smd=outerlist_smalldata
bgd=outerlist_bigdata
bench_small=benchmark(rfun(smd),cf_copy(smd),cf_shallow(smd),cf_shallowstrict(smd),cf_struct(smd),cf_structshallow(smd), order="relative")
print(bench_small[,1:4])
## test replications elapsed relative
## 3 cf_shallow(smd) 100 0.03 1.000
## 4 cf_shallowstrict(smd) 100 0.03 1.000
## 2 cf_copy(smd) 100 0.08 2.667
## 1 rfun(smd) 100 0.14 4.667
## 6 cf_structshallow(smd) 100 0.39 13.000
## 5 cf_struct(smd) 100 0.40 13.333
......和大数据
## test replications elapsed relative
## 3 cf_shallow(bgd) 100 3.47 1.000
## 4 cf_shallowstrict(bgd) 100 3.54 1.020
## 1 rfun(bgd) 100 11.28 3.251
## 2 cf_copy(bgd) 100 17.52 5.049
## 6 cf_structshallow(bgd) 100 51.51 14.844
## 5 cf_struct(bgd) 100 64.82 18.680