简体   繁体   English

在嵌套循环中避免过多的“声明 Rcpp List 的相同元素”

[英]Avoid too many “declare same elements of Rcpp List” in nested loops

I would like to ask about how to save computational time about accessing List in nested loop.我想问一下如何节省在嵌套循环中访问 List 的计算时间。 Here is an Rcpp example including two functions:这是一个包含两个函数的 Rcpp 示例:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <Rcpp.h>

// [[Rcpp::export]]
void first(const Rcpp::List ETA
          ,const int N
          ,const int I
                      ) {   
    for(int i = 0; i < I; ++i) {
        arma::rowvec eta = ETA[i];
        for(int n = 0; n < N; ++n) {
            // use eta to do some calculation
        }
    }
}

// [[Rcpp::export]]
void second(const Rcpp::List ETA
           ,const int N
           ,const int I
                      ) {   
    for(int n = 0; n < N; ++n) {
        for(int i = 0; i < I; ++i) {
            arma::rowvec eta = ETA[i];
            // use eta to do some calculation
        }
    }
}

Compare the time in R:比较 R 中的时间:

Rcpp::sourceCpp("test.cpp") # save the above code as "test.cpp"
ETA = list()
N = 10^8
I = 10
for (i in 1:I) ETA[[i]] = rep(0,i) # just an example.
ptm <- proc.time(); first(ETA,N,I); print((proc.time() - ptm))
#    user  system elapsed 
#       0       0       0 
ptm <- proc.time(); second(ETA,N,I); print((proc.time() - ptm))
#    user  system elapsed 
#   16.69    0.00   16.69

Here the ETA is a list whose each element can either have dynamic length (vector) or dynamic dimension (matrix).这里的ETA是一个列表,其中每个元素可以具有动态长度(向量)或动态维度(矩阵)。 In this code, the first way is much faster than the second way.在这段代码中,第一种方式比第二种方式快得多。 But for practical needs, the second way can reduce computational time when there are other variables iterated over n .但是对于实际需要,当有其他变量迭代n时,第二种方式可以减少计算时间。

Questions:问题:

For either first way or second way, can we declare the eta outside (before) the loops so that we don't need to declare the same eta so many times?对于第一种方式或第二种方式,我们可以在循环之外(之前)声明eta ,以便我们不需要多次声明相同的eta吗?

You're doing an implicit conversion and a deep copy during every loop, so it's no surprise that the compiler can't optimize that away.您在每个循环期间都在进行隐式转换和深层复制,因此编译器无法优化它也就不足为奇了。

What you can do is pre-calculate all the etas and store them in a vector.您可以做的是预先计算所有 etas 并将它们存储在向量中。 (I filled in some work within the loop, since empty loops can be optimized out completely). (我在循环中填写了一些工作,因为可以完全优化空循环)。

// [[Rcpp::export]]
double third(const Rcpp::List ETA
              ,const int N
              ,const int I) {   
  double output=0;
  
  // pre-create eta rowvecs
  std::vector<arma::rowvec> eta_vec(Rf_xlength(ETA));
  for(int i = 0; i < I; ++i) {
    eta_vec[i] = arma::rowvec(Rcpp::NumericVector(ETA[i]));
  }
  
  for(int n = 0; n < N; ++n) {
    for(int i = 0; i < I; ++i) {
      output += sum(eta_vec[i]);
    }
  }
  return output;
}

Results:结果:

> ptm <- proc.time(); first(ETA,N,I); print((proc.time() - ptm))
[1] 0
   user  system elapsed 
  2.761   0.000   2.761 
> #    user  system elapsed 
> #       0       0       0 
> ptm <- proc.time(); second(ETA,N,I); print((proc.time() - ptm))
[1] 0
   user  system elapsed 
 29.935   0.000  29.930 
> 
> ptm <- proc.time(); third(ETA,N,I); print((proc.time() - ptm))
[1] 0
   user  system elapsed 
  2.599   0.000   2.598 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM