如何使用多个for循环使Rcpp代码高效?
我试图通过从R调用来实现以下Rcpp代码。计算时间非常慢。涉及到很多for循环如何使用多个for循环使Rcpp代码高效?,r,rcpp,R,Rcpp,我试图通过从R调用来实现以下Rcpp代码。计算时间非常慢。涉及到很多for循环 #include <RcppArmadillo.h> using namespace Rcpp; // [[Rcpp::depends(RcppArmadillo)]] // [[Rcpp::export]] arma::mat qpart( const int& n, const int& p, const int& m, arm
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat qpart(
const int& n,
const int& p,
const int& m,
arma::vec& G,
arma::vec& ftime,
arma::vec& cause,
arma::mat& covs,
arma::mat& S1byS0hat,
arma::vec& S0hat,
arma::vec& expz){
arma::mat q(n,p);
q.zeros();
for(int u=0;u<n;++u){
arma::mat q1(1,p);
q1.zeros();
for(int iprime=0;iprime<n;++iprime){
for(int i=0;i<n;++i){
if(cause(iprime)==1 & cause(i)>1 & (ftime(i) < ftime(u)) & (ftime(u) <= ftime(iprime))){
q1 += (covs.row(i) - S1byS0hat.row(iprime))*G(iprime)/G(i)*expz(i)/S0hat(iprime);
}
}
}
q.row(u) = q1/(m*m);
}
return q;
}
正如我们所看到的,计算时间非常长
q = matrix(0,n,p)
for(u in 1 : n){
q1 <- matrix(0,p,1)
for(iprime in 1 : n){
for(i in 1 : n){
if(cause[iprime]==1 & cause[i]>1 & (time[i]<time[u]) & (time[u] <= time[iprime])){
q1 = q1 + (covs[i,] - S1byS0hat[,iprime])*G[iprime]/G[i]*expz[i]/S0hat[iprime]
}
}
}
q[u,] = q1/(m*m)
}
相同的代码在R中实现,计算时间非常长
q = matrix(0,n,p)
for(u in 1 : n){
q1 <- matrix(0,p,1)
for(iprime in 1 : n){
for(i in 1 : n){
if(cause[iprime]==1 & cause[i]>1 & (time[i]<time[u]) & (time[u] <= time[iprime])){
q1 = q1 + (covs[i,] - S1byS0hat[,iprime])*G[iprime]/G[i]*expz[i]/S0hat[iprime]
}
}
}
q[u,] = q1/(m*m)
}
q=矩阵(0,n,p)
对于(1:n中的u){
q1 1&(时间[i]某些条件仅取决于u
和iprime
,因此您可以提前检查它们。
您还可以预计算一些内容。这将提供:
arma::mat qpart2(
double m,
arma::vec& ftime,
arma::vec& cause,
arma::mat& covs,
arma::mat& S1byS0hat,
arma::vec& G_div_S0hat,
arma::vec& expz_div_G){
double m2 = m * m;
int n = covs.n_rows;
int p = covs.n_cols;
arma::mat q(n, p, arma::fill::zeros);
for (int u = 0; u < n; u++) {
double ftime_u = ftime(u);
for (int iprime = 0; iprime < n; iprime++) {
if (cause(iprime) == 1 && ftime_u <= ftime(iprime)) {
for (int i = 0; i < n; i++) {
if (cause(i) > 1 && ftime(i) < ftime_u) {
double coef = G_div_S0hat(iprime) * expz_div_G(i);
for (int j = 0; j < p; j++) {
q(u, j) += (covs(i, j) - S1byS0hat(iprime, j)) * coef;
}
}
}
}
}
for (int j = 0; j < p; j++) q(u, j) /= m2;
}
return q;
}
arma::mat qpart2(
双m,
arma:vec和ftime,
arma:vec和cause,
arma::mat&covs,
arma::mat和S1byS0hat,
arma:vec&G部门,
arma::vec和expz____G){
双m2=m*m;
int n=covs.n_行;
int p=covs.n_cols;
arma::matq(n,p,arma::fill::zero);
对于(int u=0;u
使用qpart2(m,ftime,cause,covs,t(S1byS0hat),G/S0hat,expz/G)
需要3.7秒(与您的代码相比32秒)
**
小评论:
- 您使用arma结构而不是Rcpp结构有什么原因吗
- 您应该按列而不是按行访问矩阵,因为它们是按列存储的,所以应该快一点
如果你的代码< < /Cord>语句是错误的。在C++中,<代码>和<代码>是按位的。你需要一个逻辑的<代码>和/和代码>。否则,<代码>如果语句将基本上总是被评估为true并运行贵计算。结果将是错误的,计算速度比它需要的要慢。@ Allan Cameron实际上我在R中编写了相同的代码,R的结果与使用Rcpp产生的结果完全相同。好的,我将尝试使用&。@Allan Cameron是的,通过这一更改,计算时间减少到10.3秒。您看到了任何进一步的改进吗?@Allan Cameron您认为只使用R并尝试在R中优化会更好吗?您在做什么计算?当您设置n=2000并执行三重嵌套循环时,您正在执行2000 x 2000 x 2000,或80亿次计算。在10秒内运行它意味着您在Rcpp中每秒将获得近10亿次计算。这并不慢,而是快。除非有更好的算法完成您正在尝试的任务,否则这将需要很长时间要实现。除非你能告诉我们,否则你会努力让它变得更好。Prive哇。这是一个很大的改进。你是说如果我们使用Rcpp结构,那么我们可以进一步改进。我没有理由使用arma结构。我只是更熟悉它。不,它不会提高速度,但会更简单,而且可以删除一个依赖项。是否有可能通过使用vector-through-out-Rcpp来提高效率。我之所以这样问,是因为用C编写的类似代码(不是我写的)要比上面快得多。