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

稀疏矩阵乘法的执行时间

  •  0
  • buzaku  · 技术社区  · 7 年前

    我正在进行的乘积扩散研究中的一个关键步骤涉及稀疏矩阵与向量的乘积。下面的代码复制了Rcpp和R中版本的代码。

    #define ARMA_64BIT_WORD
    #include <RcppArmadillo.h>
    //[[Rcpp::depends(RcppArmadillo)]]
    
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    arma::vec multiply(arma::sp_mat A, arma::vec nodes_status) {
    
      return A * nodes_status;
    }
    
    
    /***R
    
    library(rbenchmark)
    library(igraph)
    
    g <- sample_smallworld(dim = 1, size = 1e5, nei = 12, p = 0.65)
    
    nodes <- V(g)
    A <- get.adjacency(g)
    
    nodes.status <- sample(x = c(0, 1), 
                           size = length(nodes), 
                           replace = TRUE, 
                           prob = c(0.9, 0.1))
    
    multiplyR <- function(A, n) {return(as.vector(A %*% n))}
    
    sum(multiply(A, nodes.status) == multiplyR(A, nodes.status)) == 1e5 # check if the results are the same
    
    benchmark(multiply(A, nodes.status), multiplyR(A, nodes.status), order = "relative")[, 1:4]
    
    */ 
    

    当我运行这段代码时,两个函数的答案都是一致的,但执行时间如下:

                        test     replications elapsed relative
    2 multiplyR(A, nodes.status)          100    1.30    1.000
    1  multiply(A, nodes.status)          100    3.66    2.815
    

    这里的代码有什么问题?对于我的例子,Rcpp中有没有更有效的乘法习语?

    1 回复  |  直到 7 年前
        1
  •  1
  •   coatless    7 年前

    不。这里记录的问题有两个方面:

    1. 这个 转换时间 需要在中转换稀疏矩阵 R RcppArmadillo公司 对象大于 Matrix 的使用 C 日常工作。
    2. 成本 正在复制 vs。 参考 创造

    关于2。,施工 arma::sp_mat 使用副本,因为它没有引用(例如。 &

    #define ARMA_64BIT_WORD
    #include <RcppArmadillo.h>
    
    //[[Rcpp::depends(RcppArmadillo)]]
    
    // [[Rcpp::export]]
    arma::vec sp_multiply_copy(arma::sp_mat A, arma::vec nodes_status) {
      return A * nodes_status;
    }
    
    // [[Rcpp::export]]
    arma::vec sp_multiply_ref(const arma::sp_mat& A, const arma::vec& nodes_status) {
      return A * nodes_status;
    }
    

    从这里可以看出,两者的性能略有不同:

    benchmark(sp_multiply_copy(A, nodes.status),
              sp_multiply_ref(A, nodes.status),
              multiplyR(A, nodes.status), order = "relative")[, 1:4]
    
    #                                test replications elapsed relative
    # 3        multiplyR(A, nodes.status)          100   1.240    1.000
    # 2  sp_multiply_ref(A, nodes.status)          100   2.766    2.231
    # 1 sp_multiply_copy(A, nodes.status)          100   3.141    2.533
    

    说到这里,我们回到第一点: 这个 矩阵 功能 稀疏的 矩阵经过高度优化,可直接使用 . 上述例程的示例可在 R/products.R src/Csparse.c , src/dtrMatrix.c . 因此 矩阵

    现在,就是这样 也就是说,速度无法在 C++ . 特别是,如果矩阵对象在 C++ 用于与引用传递的实例化相乘(例如。 & ),那么它应该比调用 矩阵 的乘法例程。