Rcpp - 使用更大的列表

时间:2017-01-27 19:39:30

标签: r rcpp

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

假设我们想为每个列表做一个简单的矩阵乘法。 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

现在让我们在Rcpp中做。不同版本:

  • Vanilla Armadillo(复制对象)
  • 带有浅拷贝的犰狳
  • 具有浅拷贝和固定尺寸的犰狳
  • Vanilla struct
  • 具有初始浅拷贝的结构(但最终结构创建会复制对象)

犰狳

    #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

0 个答案:

没有答案