C++ 将循环从R转换为C++;使用Rcpp

C++ 将循环从R转换为C++;使用Rcpp,c++,r,rcpp,C++,R,Rcpp,我想使用Rcpp提高一些R代码的速度。然而,我对C++的知识很少。因此,我检查了Rcpp提供的文档,以及在Dirk Eddelbuttel的网站上提供的其他文档。在阅读了所有的内容之后,我尝试执行一个用R编写的简单循环。不幸的是,我无法执行。以下是R函数: Inverse Wishart beta = matrix(rnorm(15),ncol=3) a = rnorm(3) InW = function(beta,a) { n = nrow(beta) p = nco

我想使用Rcpp提高一些R代码的速度。然而,我对C++的知识很少。因此,我检查了Rcpp提供的文档,以及在Dirk Eddelbuttel的网站上提供的其他文档。在阅读了所有的内容之后,我尝试执行一个用R编写的简单循环。不幸的是,我无法执行。以下是R函数:

Inverse Wishart

beta = matrix(rnorm(15),ncol=3)

a = rnorm(3) 

InW = function(beta,a) {

    n = nrow(beta)
    p = ncol(beta)
    I = diag(rep(1,times = p))
    H = matrix(0,nrow=p,ncol=p)
    for(i in 1:n){
    subBi = beta[i,]
          H = H + tcrossprod(a - subBi)
        }
    H = H + p * I

    T = t(chol(chol2inv(chol(H))))
    S = 0
    for(i in 1:(n+p)){
        u <- rnorm(p)
        S = S + tcrossprod(T %*% u)
        }
    D = chol2inv(chol((S)))
    ans = list(Dinv = S,D=D)
}
逆威斯哈特
β=矩阵(rnorm(15),ncol=3)
a=rnorm(3)
InW=函数(β,a){
n=nrow(β)
p=ncol(β)
I=diag(rep(1,乘以=p))
H=矩阵(0,nrow=p,ncol=p)
for(1:n中的i){
subBi=beta[i,]
H=H+tcrossprod(a-subBi)
}
H=H+p*I
T=T(chol(chol2inv(chol(H)))
S=0
对于(1中的i:(n+p)){

RcppArmadillo的一个基本例子是这样的

require(RcppArmadillo)
require(inline)

code <- '
  arma::mat beta = Rcpp::as<arma::mat>(beta_);
  int n = beta.n_rows; int p = beta.n_cols;
  arma::mat Ip = arma::eye<arma::mat>( p, p );
  int ii;
  double S=0;
  for (ii=0; ii<(n+p); ii++) {
    S += ii; // dummy calculation
  }
  return Rcpp::wrap(S);
 '

fun <- cxxfunction(signature(beta_ ="matrix"),
                       code, plugin="RcppArmadillo")

m <- matrix(1:9,3)
fun(m)
require(RcppArmadillo)
需要(内联)

代码RcppArmadillo的一个基本示例如下所示

require(RcppArmadillo)
require(inline)

code <- '
  arma::mat beta = Rcpp::as<arma::mat>(beta_);
  int n = beta.n_rows; int p = beta.n_cols;
  arma::mat Ip = arma::eye<arma::mat>( p, p );
  int ii;
  double S=0;
  for (ii=0; ii<(n+p); ii++) {
    S += ii; // dummy calculation
  }
  return Rcpp::wrap(S);
 '

fun <- cxxfunction(signature(beta_ ="matrix"),
                       code, plugin="RcppArmadillo")

m <- matrix(1:9,3)
fun(m)
require(RcppArmadillo)
需要(内联)

代码我的第一个问题的答案如下所示。这可能不是有效的方法,但Rcpp代码给出的结果与R代码相同。我感谢巴蒂斯特的帮助

code <- '<br/>
arma::mat beta = Rcpp::as<arma::mat>(beta_);
arma::rowvec y = Rcpp::as<arma::rowvec>(y_);
int n = beta.n_rows; int p = beta.n_cols;
arma::mat Ip = arma::eye<arma::mat>( p, p );
int ii;
arma::mat H1 = beta,  d;
arma::mat H2=H1.zeros(p,p);
arma::rowvec S;
for (ii=0;ii<n;ii++){
S= beta.row(ii);
d = trans(y - S)*(y-S);
H2 = H2 + d ;
}
arma::mat H = chol(H2+p*Ip);
arma::mat Q , R;
 qr(Q,R,H);
arma::mat RR = R;
arma::mat TT = trans(chol(solve(trans(RR)*RR,Ip)));
int jj;
arma::mat SS = H1.zeros(p,p);
arma::colvec u;
arma::colvec V;
for(jj=0;jj<(n+p);jj++) {
       u = rnorm(p);
       V = TT*u;
      SS = SS + V * trans(V);
      }
arma::mat SS1 = chol(SS);
arma::mat Q1 , R1;
qr(Q1,R1,SS1);
arma::mat SS2 = R1;
arma::mat D = solve(trans(SS2)*SS2,Ip);
return Rcpp::List::create(Rcpp::Named("Dinv")=SS,Rcpp::Named("D")=D);
'
fun = cxxfunction(signature(beta_ ="matrix",y_="numeric"),code, plugin="RcppArmadillo")
m = matrix(rnorm(100),ncol=5)
vec = rnorm(5)
fun(m,vec) 

code我的第一个问题的答案如下所示。这可能不是有效的方法,但Rcpp代码给出的结果与R代码相同。我感谢巴蒂斯特的帮助

code <- '<br/>
arma::mat beta = Rcpp::as<arma::mat>(beta_);
arma::rowvec y = Rcpp::as<arma::rowvec>(y_);
int n = beta.n_rows; int p = beta.n_cols;
arma::mat Ip = arma::eye<arma::mat>( p, p );
int ii;
arma::mat H1 = beta,  d;
arma::mat H2=H1.zeros(p,p);
arma::rowvec S;
for (ii=0;ii<n;ii++){
S= beta.row(ii);
d = trans(y - S)*(y-S);
H2 = H2 + d ;
}
arma::mat H = chol(H2+p*Ip);
arma::mat Q , R;
 qr(Q,R,H);
arma::mat RR = R;
arma::mat TT = trans(chol(solve(trans(RR)*RR,Ip)));
int jj;
arma::mat SS = H1.zeros(p,p);
arma::colvec u;
arma::colvec V;
for(jj=0;jj<(n+p);jj++) {
       u = rnorm(p);
       V = TT*u;
      SS = SS + V * trans(V);
      }
arma::mat SS1 = chol(SS);
arma::mat Q1 , R1;
qr(Q1,R1,SS1);
arma::mat SS2 = R1;
arma::mat D = solve(trans(SS2)*SS2,Ip);
return Rcpp::List::create(Rcpp::Named("Dinv")=SS,Rcpp::Named("D")=D);
'
fun = cxxfunction(signature(beta_ ="matrix",y_="numeric"),code, plugin="RcppArmadillo")
m = matrix(rnorm(100),ncol=5)
vec = rnorm(5)
fun(m,vec) 

code它看起来像是
RcppEigen
RcppArmadillo
的作业。您需要的大多数R函数在这些包中都有一个直接的等价物。我建议您尝试使用一个更基本的
for
循环,逐步添加新行,并根据R等价物检查每个结果。首先,您是否将代码分析为f找出瓶颈在哪里?可能只是a=rnorm(3)代码在开头(提示:否,不是)而且,花数小时优化只占用1%时间的代码是没有意义的。分析可能会告诉您哪些循环占用的时间最长,然后您只需Rcpp这一点。这将节省您的时间。由于数据集很大,代码实际上是一个函数的一部分,运行100000次迭代需要3个多小时。我提交了这个部分代码作为示例,让我了解Rcpp如何处理循环,重点是“for(I in 1:n){subBi=beta[I,];H=H+tcrossprod(a-subBi)}”。为什么不发布一个最小的、可复制的示例,以便我可以修改下面的答案呢?它看起来像是
RcppEigen
RcppArmadillo
的工作。您需要的大多数R函数在这些包中都有直接的等价物。我建议您尝试使用更基本的
for
循环,逐步添加新行,然后检查首先,你有没有分析过你的代码以找出瓶颈在哪里?可能只是a=rnorm(3)代码在开始时(提示:否,不是)而且,花数小时优化只占用1%时间的代码是没有意义的。分析可能会告诉您哪些循环占用的时间最长,然后您只需Rcpp这一点。这将节省您的时间。由于数据集很大,代码实际上是一个函数的一部分,运行100000次迭代需要3个多小时。我提交了这个部分代码作为示例,让我了解Rcpp如何处理循环,重点是“for(I in 1:n){subBi=beta[I,];H=H+tcrossprod(a-subBi)}。为什么不发布一个最小的、可复制的示例,以便我可以修改下面的答案?