Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用C+编写的效率极低的代码+;_C++_R_Rcpp_Rcpparmadillo - Fatal编程技术网

C++ 用C+编写的效率极低的代码+;

C++ 用C+编写的效率极低的代码+;,c++,r,rcpp,rcpparmadillo,C++,R,Rcpp,Rcpparmadillo,以下函数的计算时间非常长。还有改进的余地吗?我是否应该以不同的方式访问矩阵X的元素?我感谢您的任何意见或建议 #include <RcppArmadillo.h> using namespace Rcpp; using namespace arma; // [[Rcpp::depends(RcppArmadillo)]] // [[Rcpp::export]] arma::mat myfunc(const int& n, const i

以下函数的计算时间非常长。还有改进的余地吗?我是否应该以不同的方式访问矩阵
X
的元素?我感谢您的任何意见或建议

#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]


arma::mat myfunc(const int& n,
                 const int& p,
                 arma::mat& X,
                 arma::rowvec& y,
                 const arma::rowvec& types,
                 const arma::mat& rat,
                 const arma::rowvec& betas){
  
  arma::mat final(p+p,n);
  final.zeros();
  int i,j;
  
  for(i=0; i < n; ++i){
    arma::colvec finalfirst(p+p); finalfirst.zeros();
    for(j=0; j < n; ++j){
      arma::mat Xt = X * log(y(j));
      arma::mat finalX = join_rows(X,Xt);
      
      arma::rowvec Xi = finalX.row(i);
      
      if(types(i)==1 && y(j)==y(i)){
        finalfirst += (Xi.t() - rat.col(j));
      }
      if(types(i)>1 && y(j) > y(i)){
        finalfirst -= (Xi.t() - rat.col(j)) * exp(arma::as_scalar(betas*Xi.t()));
        
      }
      else if(y(j) <= y(i)){
        finalfirst -= Xi.t() * exp(arma::as_scalar(betas*Xi.t()));
      }
    }
    
    final.col(i) = finalfirst;
  }
  
  return(final);
}




/*** R
m=4000
types = runif(m,0,5)
types[types<=1] = 0 ; types[types > 1 & types < 3] = 1; types[types>=3]=2
microbenchmark(out = myfunc(n=m,p=2,X=matrix(rnorm(m*2),nrow=m,ncol=2),y=runif(m,0,3),types=types,rat=matrix(rnorm(m*4),nrow=4,ncol=m),betas=c(1,2,3,4)))
*/
#包括
使用名称空间Rcpp;
使用arma;
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::导出]]
arma::mat myfunc(常数整数和整数),
康斯特国际公司,
arma:mat&X,
阿尔玛:罗维克和y,
常量arma::行向量和类型,
常数arma::mat和rat,
常数arma::rowvec和betas){
arma::mat final(p+p,n);
final.zeros();
int i,j;
对于(i=0;i1和&y(j)>y(i)){
finalfirst-=(Xi.t()-rat.col(j))*exp(arma::as_标量(betas*Xi.t());
}
如果(y(j)=3]=2
微基准(out=myfunc(n=m,p=2,X=matrix(rnorm(m*2),nrow=m,ncol=2),y=runif(m,0,3),types=types,rat=matrix(rnorm(m*4),nrow=4,ncol=m),betas=c(1,2,3,4)))
*/

如果您至少对您正在做的事情提供一些解释,可能会有所帮助

首先,我建议将代码分成非常小的块,对每个块进行微基准标记,并找到瓶颈操作。这比一次将整个函数扔到墙上要好

行访问与列访问
join_行(X,Xt)

这是一个非常缓慢的操作,尤其是因为您要将
rowvec
添加到一个面向列的
mat
。犰狳矩阵以列大顺序存储为向量,因此幕后犰狳在n个非连续位置调用
push_back
,其中n是列数

似乎您可以完全避免这种情况,因为
finalX.row(i)
是此循环中唯一依赖于
finalX
的调用。只需找出
.row(i)
是什么

隐式操作 你做了很多转置,也许你应该从一开始就使用转置矩阵

Xi.t()
在同一行中被调用两次:
finalfirst-=(Xi.t()-rat.col(j))*exp(arma::as_scalar(betas*Xi.t());

转置行向量是毫无意义的,只需将其初始化为列向量,然后使用一个好的老式循环对其进行迭代即可。多编写一点代码并不总是一件坏事,它通常也会使您的意图更加明确

复制与就地操作 这是一份:
final.col(i)=finalfirst;

为什么不在内存中运行并更新
final(u,i)
就地,而不是使用临时的
finalfirst
,然后在目标矩阵中进行深度复制?这是一列,因此内存是连续的,编译器将能够为您优化访问模式,就像您处理任何简单向量一样

综上所述,我还没有完全理解你到底在做什么,但是@maximum_prime_is_463035818关于切换(I..)的
和(j..
循环的
可能是正确的。看起来你将能够从嵌套循环中拉出这两行:

arma::mat Xt = X * log(y(j));
arma::mat finalX = join_rows(X,Xt);

因为它们根本不依赖于
i

这可能更适合于代码审查。内部循环中的所有内容都经过n*n次计算,但是
arma::mat Xt=X*log(y(j));arma::mat finalX=join_rows(X,Xt)
仅取决于
j
,我没有进一步研究,但这看起来你可以交换循环或用内存换取cpu周期。了解这段代码的功能将是有益的,我们可以知道它是否正确,它的时间复杂度是否最佳。@RetiredInja它在那里吸引了反对票和接近票,而它在那里谢谢。我会考虑你的建议。