代码之家  ›  专栏  ›  技术社区  ›  VFreguglia

从另一个函数中调用时,Rcpp函数性能降低

  •  0
  • VFreguglia  · 技术社区  · 5 年前

    我正在重写一些旧代码以使用新类型的参数表示。旧版本使用矩阵表示参数,而新版本使用 List arma::fcube . 我得到了一个性能损失,只有在从另一个函数中多次调用该函数时才能观察到:

    旧功能 ConditionalProbs conditional_probabilities . 另一方面, multiple_times_old (它要求 条件罗伯斯 多次)大约比 multiple_times_new ,即使此函数之间的唯一区别是多次调用的函数。

    我为长代码道歉:这是我的旧代码(注意,我使用的是 NumericMatrix IntegerMatrix 关于新代码)

    // [[Rcpp::depends(RcppArmadillo)]]
    // [[Rcpp::export]]
    NumericVector ConditionalProbs(NumericMatrix X, IntegerVector position,  int C, NumericMatrix cMat, NumericMatrix vMat, NumericVector V) {
    
      int n = X.nrow(); int m = X.ncol();
      int n_neighbors = cMat.nrow();
      int x = position[0] -1; int y = position[1] -1;
      int neix, neiy;
      NumericVector p(C + 1);
      IntegerVector vals = seq_len(C+1) - 1;
      double U;
      int dif;
    
      for(int value = 0; value <= C; value++){
        U = V[value];
        for(int ne=0; ne < n_neighbors; ne++){
          neix = x + cMat(ne,0); neiy = y + cMat(ne,1);
          if(neix < n && neix >=0 && neiy < m && neiy>=0){
            dif = X(neix,neiy) - vals[value] ;
            U = U + vMat(ne,dif+C);
          }
        }
        p[value] = exp(U);
      }
      p = p/sum(p);
      return(p);
    }
    
    
    // [[Rcpp::depends(RcppArmadillo)]]
    // [[Rcpp::export]]
    NumericMatrix multiple_times_old(NumericMatrix X, NumericMatrix cMat, NumericMatrix vMat, NumericVector V, int C, int n_times){
      NumericVector probability;
      int N = X.nrow(); int M = X.ncol();
      int x,y;
      IntegerVector position(2);
      for(int i = 0; i < n_times; i++){
        x = 2;
        y = 2;
        position[0] = x; position[1] = y;
        probability = ConditionalProbs(X, position, C, cMat, vMat, V);
      }
      return(X);
    }
    

    现在新版本是:

    // [[Rcpp::depends(RcppArmadillo)]]
    // [[Rcpp::export]]
    NumericVector conditional_probabilities(IntegerMatrix X, IntegerVector position, List R, arma::fcube theta){
      int n_neighbors = theta.n_rows;
      int C = theta.n_cols - 1;
      int x = position[0] - 1; int y = position[1] - 1;
      int N = X.nrow(); int M = X.ncol();
    
      IntegerVector this_pos;
      NumericVector probs(C+1);
      float this_prob;
      int dx, dy;
    
      for(int value = 0; value <= C; value++){
        this_prob = 0;
        for(int i = 0; i < n_neighbors; i++){
          this_pos = as<IntegerVector>(R[i]);
          dx = this_pos[0]; dy = this_pos[1];
          if(0 <= x+dx && x+dx < N && 0 <= y+dy && y+dy < M){
            this_prob = this_prob + theta(i, value, X(x+dx, y+dy));}
          //if(0 <= x-dx && x-dx < N && 0 <= y-dy && y-dy < M){
          // this_prob = this_prob + theta(i, X(x-dx, y-dy), value);}
        }
        probs[value] = exp(this_prob);
      }
      return(probs/sum(probs));
    }
    
    // [[Rcpp::depends(RcppArmadillo)]]
    // [[Rcpp::export]]
    IntegerMatrix multiple_times_new(IntegerMatrix X, List R, arma::fcube theta, int n_times){
      NumericVector probability;
      int N = X.nrow(); int M = X.ncol();
      int x,y;
      IntegerVector position(2);
      for(int i = 0; i < n_times; i++){
        x = 2;
        y = 2;
        position[0] = x; position[1] = y;
        probability = conditional_probabilities(X, position, R, theta);
      }
      return(X);
    }
    

    我编写了测试函数的基准:

    library(Rcpp)
    sourceCpp("bench.cpp") #All the c++ functions are on this file
    
    # parameters for old functions
    cMat <- matrix(c(1,0,0,1), nrow = 2, byrow = TRUE)
    vMat <- matrix(c(-1,-1,-1,-1,1,-1,-1,-1,-1,
                     -1,-1,-1,-1,1,-1,-1,-1,-1), nrow = 2, byrow = TRUE)
    vMat <- rbind(vMat, vMat) + 0.0
    cMat <- rbind(cMat, -cMat)
    V <- rep(0.0,5)
    
    # parameters for new functions
    R <- list(c(1L,0L), c(0L,1L), c(-1L,0L), c(0L, -1L))
    theta <- array(0, c(4,5,5))
    theta[1,,] <- theta[2,,] <- theta[3,,] <- theta[4,,] <- diag(rep(2,5)) - 1.0
    
    X <- matrix(sample(0:4,64*64, replace = TRUE), nrow = 64)
    
    library(rbenchmark)
    
    benchmark(ConditionalProbs = ConditionalProbs(X, c(30,30), 4, cMat, vMat, V),
              conditional_probabilities = conditional_probabilities(X, c(30,30), R, theta), 
              replications = 50000)[ ,c("test", "relative","elapsed", "replications")]
    
                           test relative elapsed replications
    2 conditional_probabilities    1.000   0.314        50000
    1          ConditionalProbs    1.538   0.483        50000
    
    benchmark(multiple_times_old = multiple_times_old(X, cMat2, vMat2, V, 4, 50000),
              multiple_times_new = multiple_times_new(X, R, theta, 50000),
              replications = 10)[ ,c("test", "relative", "elapsed", "replications")]
    
                    test relative elapsed replications
    2 multiple_times_new    4.359   0.959           10
    1 multiple_times_old    1.000   0.220           10
    

    多次更新 慢于 如果第一个调用的函数比第二个调用的函数快?

    0 回复  |  直到 5 年前
    推荐文章